分布式专题-3、事务失效
1. 失效原因
1.1. Bean 是否是代理对象⭐️🔴
1.2. 入口函数是否是 public 的⭐️🔴

AbstractFallbackTransactionAttributeSource#computeTransactionAttribute

allowPublicMethodsOnly 方法由子类 AnnotationTransactionAttributeSource 实现,该子类方法中默认是 true,所以当你加了事务注解的方法不是 public 时,该方法直接返回 null
1.3. 是否支持事务
数据库是否支持事务 (Mysql 的 Mylsam 不支持事务),行锁才支持事务
1.4. 切点是否配置正确
1.5. 内部方法间调用导致事务失效⭐️🔴
1.5.1. 解决方案 1
再声明一个 service,自己注入自己,将内部调用改为外部调用
1.5.2. 解决方案 2
因为 this 不是代理对象,可以配置 expose-proxy=”true”,就可以通过 AopContext.currentProxy() 获取到当前类的代理对象。
1 | |
1.5.3. 解决方案 3
使用编程式事务

1.6. 异常类型是否配置正确 (回滚策略)⭐️🔴

默认只支持非受检 (检查) 异常:RuntimeException 和 Error,不支持受检 (检查) 异常。
想要支持检查异常需要配置 rollbackFor
@Transactional(rollbackFor = Exception.class)


TransactionInterceptor#invoke
TransactionAspectSupport#invokeWithinTransaction
TransactionAspectSupport#completeTransactionAfterThrowing
rollbackOn(Throwable ex)

1.6.1. 为什么默认只支持非受检异常⭐️🔴
配置了这个,Exception 异常的事务,就会生效,如果没有配置则使用父类的默认配置逻辑如下:❕
DefaultTransactionAttribute
1.7. 异常被 catch 住了
代码中手动 catch 了异常,然后又未抛出来,此时事务就不生效了。
解决方法:要么不 catch 需要回滚的异常,要么 catch 之后再抛出,要么手动回滚
1.7.1. 解决方案 1
catch 之后往外抛异常
1.7.2. 解决方案 2
catch 之后,设置手动回滚


