Spring事物传播机制
- REQUIRED:支持当前的事务;如果当前没有,那么创建一个新的。这也是 Spring 默认的传播行为。比如,方法 A 调用了方法 B,A B都开启 REQUIRED 级别的事务。那么,B 方法会发现有了当前事务 A,那么 B 就会加入到 A 的事务中。如果 A 没有开启事务,B 仍旧开启自己的事务。
- SUPPORTS:支持当前事务;如果没有当前事务以非事务的方式运行。
- MANDATORY:支持当前事务;如果没有会抛出异常;
- REQUIRES_NEW:始终创建一个新的事务;如果有当前事务,会把当前事务挂起;
- NOT_SUPPORTED:不支持当前事务;总是以非事务方式执行。
- NEVER:不支持当前事务;如果有当前事务会抛出异常。
- NESTED:如果当前事务存在,就以嵌套的方式运行。行为和 REQUIRED 很像。
自调用问题
方法中调用了同一个 service 的方法,比如方法 A (REQUIRED)调用了方法 B,即使 B 声明了 REQUIRS_NEW 的传播行为(始终创建一个新事务执行),但在 A 方法抛出异常的时候,B 方法还是会回滚。
原因分析:
Spring AOP 使用 JDK / Cglib 进行动态代理,它会通过代理,织入增强代码。比如调用带 @Transactional 注解的方法,会通过调用代理对象(增强后)的该方法进行。但当进行自调用的时候,方法内部调用的方法还是使用原对象进行。也就是说,Spring AOP 的代理对象只会在不同的 bean 之间相互调用的时候使用。
参考链接:https://blog.csdn.net/FangHX25/article/details/107321217
解决办法:
- 新建一个帮助类
- 将@Transactional 注解使用在具体的类上,不建议用在接口上