spring的@Transactional失效原因分析

Posted 好大的月亮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring的@Transactional失效原因分析相关的知识,希望对你有一定的参考价值。

在测试环境遇到了一次@Transactional事务失效的场景,将排查的方式记录下来。

一开始以为是aop的其他代理类影响到了,但是后面取消代理类后事务还是没有生效。尝试在插入的方法中单独加@Transactional注解但是也没生效。一般我们记忆中只要抛了异常,并且这个异常确保是可以被回滚的,那么事务是可以回滚的。但是这里明显没有回滚。

接下来就是打断点debug了,发现当进入方法,执行插入数据库的那一行代码之后,数据直接用navicat就可以查到了,说明压根没有开启事务,如果有事务的话方法都没结束事务也就没提交,navicat在默认的事务隔离级别下是查不到数据的。

到这里初步排查出来事务没有生效,此时只要排查下数据库表的ENGINE是不是innodb,再一个就是自动注入的是 PlatformTransactionManager 接口的哪个实现类。

因为事务管理器,不管是JPA还是JDBC等都实现自接口 PlatformTransactionManager.如果你添加的是 spring-boot-starter-jdbc 依赖,框架会默认注入 DataSourceTransactionManager 实例(mybatis也是注入的这个实例)。如果你添加的是 spring-boot-starter-data-jpa 依赖,框架会默认注入 JpaTransactionManager 实例。

实际注入的PlatformTransactionManager实例可以这样查看

@EnableTransactionManagement // 启注解事务管理,等同于xml配置方式的 <tx:annotation-driven />
@SpringBootApplication
public class ProfiledemoApplication {

    @Bean
    public Object testBean(PlatformTransactionManager platformTransactionManager){
        System.out.println(">>>>>>>>>>" + platformTransactionManager.getClass().getName());
        return new Object();
    }

    public static void main(String[] args) {
        SpringApplication.run(ProfiledemoApplication.class, args);
    }
}

这里参考了大佬的博文
https://blog.csdn.net/catoop/article/details/50595702
https://zhuanlan.zhihu.com/p/145897825

其他的常见的事务失效场景一般就这几种:

  1. @Transactional 应用在非 public 修饰的方法上,aop只能在public方法上切
  2. @Transactional 注解属性 propagation 设置错误,传播的值没搞对,导致事务没有传递进实际增删改的方法里
  3. @Transactional 注解属性 rollbackFor 设置错误,这个就是抛出的异常没配置好,默认是RuntimeException,也可以自己自定义,只要异常是继承自rollbackFor指定的异常,都能回滚
  4. 同一个类中方法调用,导致@Transactional失效,比如就是controller里先调用了一个方法,然后在这个方法里再调用@Transactional声明的方法,这个时候是因为先调用的时候用的是没有被aop代理的类,然后调用这个类的其他方法的时候默认使用了this关键字指向了当前对象,没有指向代理的类
  5. 异常被你的 catch“吃了”导致@Transactional失效
  6. 数据库引擎不支持事务,我遇到的就是这种,myisam是不支持事务的,只有innodb引擎支持事务

以上是关于spring的@Transactional失效原因分析的主要内容,如果未能解决你的问题,请参考以下文章

Spring 下默认事务机制中@Transactional 无效的原因

项目中Spring事务失效的场景问题排查

@Transactional注解失效的解决方案

@transactional注解在什么情况下会失效

@transactional注解在什么情况下会失效

@transactional注解在什么情况下会失效,为什么。