请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

@Transaction注解和@Async注解一起使用事务回滚

同步方法事务可以回滚,异步方法事务没有回滚

正在回答 回答被采纳积分+3

1回答

张勤一 2020-12-16 22:34:49

同学你好:

    当需要对某个方法开启异步线程,同时开启事务时,即 @Transactional 与 @Async 联合使用。这样使用的一个直接后果是明明加了 @Transactional 注解为什么事务没有成功执行。

    原因如下:

    (1)Spring 实现这两个注解的方式都是通过 AOP;

    (2)在实现时,Async 注解强制覆盖 AOP 的 order 为最小值;

    (3)但是在实现 Transactional 注解时,却没有覆盖 order,这意味着它仍然为默认的Integer.MAX_VALUE,order 可配置。所以异步切面会先于事务切面执行;

    (4)假设 @Transactional 能先于 Async 切面执行,但由于 spring 事务管理依赖的是 ThreadLocal,所以在开启的异步线程里面感知不到事务,说细点就是在 Spring 开启事务之后,会设置一个连接到当前线程,但这个时候又开启了一个新线程,执行实际的 SQL 代码时,通过 ThreadLocal 获取不到连接就会开启新连接,也不会设置 autoCommit,所以这个函数整体将没有事务。


    我是勤一,致力于将这门课程的问答区打造为 Java 知识体系知识库,Java 知识体系 BBS!共同建造、维护这门课程,我需要每一个你!



1 回复 有任何疑惑可以回复我~
  • 提问者 Wizey #1
    我写下伪代码哈
    @Transaction
    public class Test() {
          public method1() {
              dao.save(new User());
              method2();
          }
    
          @Async
          public method2() {
              dao.save(new UserRecord());
              sleep(3000);
              throw Exception();
          }
    }
    我想在异步方法出现异常的时候,回滚同步方法中的事务,请问老师有办法实现么?
    回复 有任何疑惑可以回复我~ 2020-12-16 23:05:02
  • 张勤一 回复 提问者 Wizey #2
    这样的写法其实是不合理的,如果确实需要回滚,使用手动的 try catch 实现手动回滚。
    回复 有任何疑惑可以回复我~ 2020-12-16 23:11:42
  • 提问者 Wizey 回复 张勤一 #3
    老师可以写下伪代码么,感谢
    回复 有任何疑惑可以回复我~ 2020-12-16 23:14:48
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信