Spring事务在哪些场景下会失效呢?

日常开发中,经常需要用到各种各样的事务,去控制我们的代码的执行,但是如果事务使用的不当,也是会导致事务失效,以下是几个容易导致 Spring 事务失效的场景:

事务失效的场景

在这里插入图片描述

具体原因及解决方式

一、手动抛出不支持的异常类型:
  • Spring事务默认支持RuntimeException及其子类异常,但手动抛出Exception(RuntimeException的父类)会导致事务失效。
  • 解决方案:
    • 指定Spring事务异常捕获类型:@Transactional(rollbackFor = Exception.class)

    • 或者抛出Spring事务支持的异常类型:throw new RuntimeException("手动抛出运行时异常");

二、使用了try catch捕获且未抛出异常:
  • Spring事务必须在接收到异常的时候才会去触发事务的回滚,因此假设我们在代码中try catch捕获了异常后,处理完自身逻辑后并未抛出异常,就会导致事务失效。
  • 解决方案:
    • 在catch代码块中抛出异常
三、事务方法无法被spring代理:
  • 事务注解 (@Transactional) 仅在公共方法上有效。如果注解应用在 private、protected 或 package-private 方法上,事务将不会生效。spring声明式事务是基于AOP去代理的,只能拦截public修饰的方法
  • 解决方案:
    • 确保所有带有 @Transactional 注解的方法都是 public 的
四、事务所属类未被spring容器管理:
  • spring的事务都是基于AOP去实现的,若事务所在的类未添加@service注解,也就是事务类未注册到spring容器中,那么spring的事务也是无法生效的。
  • 解决方案:
    • 确保所有带有事务的所属类被@service修饰
五、事务方法的自调用:
  • 在代码类中,若一个携带事务注解的方法调用了另一个携带事务注解的方法,那么被调用的方法的事务将会失效。因为spring的事务是基于AOP的动态代理去实现的,而同类方法的自调用或者使用this方法调用,是不会经过代理对象的,所以会导致事务的失效
  • 解决方案:
    • 方法一:将被调用的方法移到另一个服务类中
    • 方法二:将被调用的方法移到另一个服务类中
    • 方法三:使用@Autowired在本类中注入本类实例,再用注入的实例对象调用该方法。
    • 方法四(推荐):手动获取本类的代理,用代理调用该方法:((UserService)AopContext.currentProxy()).update();
六、事务所属类未被spring容器管理:
  • spring的事务其实都是基于数据库的事务去实现的,部分数据表本身不支持事务,如MySql的MyISAM引擎。
  • 解决方案:
    • 确保使用的数据库引擎支持事务,如MySql的InnoDB引擎。
七、spring事务传播级别设置不支持事务:
  • spring的事务的传播级别若使用的不恰当,也会导致事务的失效,如@Transactional(propagation = Propagation.NOT_SUPPORTED)或@Transactional(propagation = Propagation.NEVER)会导致不支持事务。
  • 解决方案:
    • 使用Spring默认的传播级别(PROPAGATION_REQUIRED),或其他支持事务的传播级别。
八、代理对象和类加载器调用:
  • 当我们使用反射,或者类加载器动态去调用事务方法的时候,会导致事务失效,因为AOP无法拦截这种形式的调用,也就无法获取到代理对象进行事务的管理。
  • 解决方案:
    • 确保所有带有 @Transactional 注解的方法都通过 Spring 管理的代理对象调用。
九、事务方法被多线程调用:
  • 在spring中,事务的上下文都是基于当前线程的,事务管理器无法将上下文中切换到新的线程,新线程中无法继承父线程的事务上下文,因而导致事务失效。
  • 解决方案:
    • 避免在事务范内启动新线程,或者在多线程环境中使用编程式事务管理。

** 若对您有帮助,希望点赞收藏~**

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值