一、前言 1.Bean是否是代理对象 2.入口函数是否是public的 3.数据库是否支持事务(Mysql的Mvlsam不支持事务),行锁才支持事务 4.切点是否配置正确 5.内部方法间调用导致事务失效 因为this不是代理对象,可以配置 expose-proxy=true,就可以通过AopContext.curr
一、前言
1.Bean是否是代理对象 2.入口函数是否是public的 3.数据库是否支持事务(Mysql的Mvlsam不支持事务),行锁才支持事务 4.切点是否配置正确 5.内部方法间调用导致事务失效 因为this不是代理对象,可以配置 expose-proxy="true",就可以通过AopContext.currentProxy()获取到当前类的代理对象。
也可以注入当前bean 6.异常类型是否配置正确 默认只支持RuntimeException和Error,不支持检查异常 想要支持检查异常需要配置rollbackFor @Transactional(rollbackFor = Exception.class) 7.异常被catch住了 代码中手动catch了异常,然后又未抛出来,此时事务就不生效了。 二、方法不是 public 的 以下来自Spring官方文档
大概意思就是 @Transactional 只能用于 public 的方法上,否则事务不会失效,如果要用在非 public 方法上,可以开启 AspectJ 代理模式。
TransactionInterceptor#invoke
TransactionAspectSupport#invokeWithinTransaction
AbstractFallbackTransactionAttributeSource#getTransactionAttribute
AbstractFallbackTransactionAttributeSource#computeTransactionAttribute
解决方案一: 再声明一个service,自己注入自己,将内部调用改为外部调用
解决方案二:
解决方案三: 使用编程式事务
我们看下TransactionInterceptor类 TransactionInterceptor#invoke
TransactionAspectSupport#invokeWithinTransaction
TransactionAspectSupport#completeTransactionAfterThrowing
配置了这个,Exception异常的事务,就会生效
代码中手动catch了异常,然后又未抛出来,此时事务就不生效了。 解决方法:要么不catch需要回滚的异常,要么catch之后再抛出,要么手动回滚
解决方案一: catch之后往外抛异常
解决方案二: catch之后,设置手动回滚
|
2021-06-05
2021-05-27
2021-05-26
2021-06-05
2021-05-16