@Transactional失效的场景(按出现频率排序)

本文分析了动态代理在@Transactional注解中的作用,讨论了私有方法、静态方法和final方法导致的代理失效问题,以及如何正确使用rollbackFor和propagation属性。还提到了数据库引擎对事务的支持情况,特别是MySQL和MyISAM引擎。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


根据可能出现的情况排序,排查时可以从上往下排查

动态代理失效

@Transactional注解是基于AOP的,AOP基于动态代理,如果动态代理失效,那么@Transactional就会失效。动态代理失效的场景如下:

  1. 事务方法是private方法:private修饰的方法,只能在类中使用,也就是this调用,这种情况是不会走到代理对象的,所以代理失效,从而事务失效。
  2. 事务方法是类内部方法:自己调自己,逻辑同private方法,代理对象是调不到的
  3. 事务方法是static方法:static是类方法,不对对象方法,但是动态代理代理的是对象,所以static方法是没办法被AOP的
  4. 事务方法是final方法:final方法是不可被修改的,换句话说是没办法覆盖的,没办法被AOP

异常被捕获

如果在事务方法内把异常给捕获了,自己处理了,那么事务方法会认为这个方法应该被commit,从而就不会触发事务回滚。

public class TestService{

    @Transactional
    public void test() {
        try {
            // 业务逻辑
            doSomething();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
}

例如以上,如果doSomething()方法抛出异常,添加了事务注解的test()方法中捕获了异常,进行了处理,那么事务就会被commit,那么事务就不可能被回滚了

注解属性用的不对

最容易用错的属性是以下两个

rollbackFor属性

rollbackFor属性指定发生什么类型的异常会触发事务回滚。一般设置成**rollbackFor= MyException.class**
这样出现非受检异常时,也可以触发事务回滚。

propagation属性

propagation属性指的是事务传播行为,Spring默认传播行为是REQUIRED,一般我们不用设置这个属性,使用默认的即可。如果使用**propagation = Propagation.NOT_SUPPORTED**就会导致事务失效,原因是Propagation.NOT_SUPPORTED以非事务的方式运行,如果当前存在事务,暂停当前的事务。

数据库引擎不支持

出现了这种情况的可能性比较少,目前主流的数据库是MySQL,MySQL默认的存储引擎是InnoDB,是支持事务的。Myisam等其他不支持事务的存储引擎比较少用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI极客Jayden 

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值