事务失效原因

  • 类的自调用:直接调用本类的方法,没有通过代理对象来调用方法,代理对象内部的事务拦截器不会拦截到这次行为。则不可能开启事务

  • 使用私有方法:因为spring的事务管理是基于AOP实现的,AOP代理无法拦截目标对象内部的私有方法调用。直接没有代理对象

  • 使用多线程:在主线程中开启的事务不会自动传播到其创建并执行的子线程中,则会失效

  • 如果事务回滚,将报错代码用try catch来进行捕获,事务就不会失效

  • 其他比如定义事务属性传播性时定义的是REQUIRES_NEW(脱离当前事务),事务也不会受到影响

声明式事务的底层原理:

  • 当目标类被spring管理时(即@Component,@Service,@controller,@Repository注解时),spring会为目标对象创建一个代理对象。代理对象负责拦截目标方法的调用,并在必要时应用事务管理(AOP思想)

  • 代理对象内部包含一个事务拦截器TransactionInterceptor,负责处理事务相关的逻辑

  • 事务拦截器会检查方法上是否添加了@Transactional注解,来决定是否应用事务(JDBC的connection调用setAutoCommit(false),然后会将connection存到ThreadLocal(本地线程)中,

    为了嵌套方法可以拿到外层事务的connection对象,只有使用同一个connection对象才能保证使用同一个事物)

    然后去执行方法,从而执行数据库操作,然后再执行嵌套方法,然后再嵌套方法的代理对象,就可以拿到外层事务的Thread Local中connection对象,从而执行方法,嵌套方法发现ThreadLocal中有值,他不会提交事务,而是统一的交给外层事务进行提交)

  • 事务拦截器在目标方法执行前后应用事务通知,(前置通知和后置通知)在方法执行前,事务拦截器启动事务;在方法执行后,根据方法的执行结果决定事务的提交或回滚

如下图所示:

多线程事务失效原因

如果在方法中开启新线程去调用嵌套方法时,这时嵌套线程就拿不到外层事务的ThreadLocal中的connection对象。

因为ThreadLocal是绑定在主线程上的。

所以在新的线程中去调用嵌套方法时,就拿不到外层事务的connection对象,

然后就会自己新建一个事务,自己存一个connection到自己的ThreadLocal中,

这样的话,方法和嵌套方法就各开启了一个事务,且是同级事务,相互不影响。

但是这样在外层事务失败回滚的时候,内层事务不受外层事务的影响,不进行回滚的话,就会造成事务回滚但还是写入数据库中的现象,我们要保证数据库数据的一致性!

解决方法

在创建一个异步线程之后,可以手动的往嵌套方法的Tread Local中将外层事务connection对象存入,那么嵌套方法就可以从自己的Thread Local中拿到外层事务的connection了,这样方法和嵌套方法用的就是同一个事务了。这样就不会出现多线程事务失效的情况了

前置知识:

编程式事务中DataSourceTransactionManager类org.springframework.jdbc.datasource.DataSourceTransactionManager中的doBegin方法就是spring底层在开启事务的时候进行调用的,在方法中获取数据库连接,并开启事务

所以如果想要获取对应的connection,需要调用事务同步管理器的getResource()方法,

然后将spring容器当中的datasource传进来,就可以拿到,

然后再调用BindResource方法就可以将异步线程中的ThreadLocal中存入外层事务的connection

解决方案代码展示:

 private DataSource datasource;
 ConnectionHolder connectionHolder = (ConnectionHolder) TransactionSynchronizedManager.getResource(dataSource);
 new Thread(()->{
 //绑定主线程的connection到子线程中
 TransactionSynchronizedManager.bindResource(dataSource,connectionHolder);
 //调用方法
 })

这样便可以解决spring事务失效的情况,希望对大家有所帮助!

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐