Sprinboot 事务不生效问题排查

背景:记一次Springboot事务不起作用问题排查

springboot项目中的Application启动类中添加@EnableTransactionManagement注解开启事务。

接下来在需要添加事务的方法上添加@Transaction注解开启事务。@Transaction注解生效有几个需要注意的地方:

1.spring事务的支持是对数据库事务的支持。所以想要使用spring开启事务,首先数据库的引擎必须是支持事务的。比如mysql的myisam引擎就不支持事务

 

2.@Transaction需要加载public类型的方法上。其他类型的方法不报错,但是事务也不会生效。

 

3.@Transaction最好制定回滚的错误类型。roll back for = "具体的错误类型"。

 

因为spring事务管理默认是只会处理unchecked的异常:也就是runtime异常及其子类和错误(error)

 

checked异常包括Exception下除了runtimeException以外的异常。spring默认不会处理这些异常。所以需要我们在使用的时候在

 

@Transaction(rollbackFor = Exception.class)来指定回滚的异常。同样,也可以指定某个异常不回滚。可以使用norollbackFor = 具体的异常。

4.因为spring是通过代理对象来回滚事务的。所以,如果在一个为开启事务的方法中,直接调用本类中其他有事务的方法时,事务会失效。例如:     


public class Test {

public void A() {

System.out.println("====> methodA");

    B();

}

@Transactional(rollbackFor = Exception.class)

public void B() {

    System.out.println("====> methodB");

}

}

无事务的方法A直接调用自己的有事务的方法B,会导致事务失效。原因是spring的事务是通过代理类实现的,自己直接调用自己的方法就没有通过代理类,所以事务不会生效。解决办法有:

       1.可以通过暴露代理类,然后再通过本类的代理类调用有事务的方法。用时要在springboot启动类上添加@EnableAspectJAutoProxy(exposeProxy = true)开启暴露代理类。


public class Test {

@Transactional(rollbackFor = Exception.class)

public void A() {

System.out.println("====> methodA");

((Test)AopContext.currentProxy()).B();

}

@Transactional(rollbackFor = Exception.class)

public void B() {

System.out.println("====> methodB");

}

}

2.可以再添加一层,将A,B方法分在不同的类里,这样也能达到开启事务的目的。

 

 

5、@Transactional(rollbackFor = Exception.class, transactionManager = "mysqlsumTransactionManager")

mysqlsumTransactionManager 是自定义的数据源名称(当你的应用为多数据源时), 自定义数据源及事务管理器 回滚要指定,否则回滚不生效,而且要加在方法上面,加载类上无法生效启动类也上开启事务。

 

6、aop切片 包裹事务导致事务不生效原因:

单数据源,手动配置datasource也不生效,问题不在于此。

添加异常controller adive处理异常的时候发现,异常信息没有被拦截处理,而是被service层aspect around拦截打出堆栈信息处理了,如图:

 

打出堆栈信息说明service层异常被捕获处理了,导致事务管理机制无法检测到事务。

尝试1:注释掉around aspect 事务生效,说明around拦截service处理了异常,导致事务没有回滚。 难道这里区分processJoinPoint 和JoinPoint的区别?

测试  切片的around 环绕通知换成before前置通知,事务生效,即将service层的around aspect 修改成before即可解决事务问题。

尝试2:切service日志around处理为什么不影响事务?

再次尝试修改service层around通知方法,发现catch异常后是reture exception 并不是throw exception

修改around通知中捕获处理异常后,不要return(return 异常信息被加工处理),直接抛出即可,事务生效。

 

现在重新来看一下spring事务机制,像回环加工厂一样,最先处理的最后响应。

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值