7种事务的传播机制(可通过spring配置或注解来设置)
REQUIRED(默认):支持使用当前事务,如果当前事务不存在,创建一个新事务。
REQUIRES_NEW:创建一个新事务,如果当前事务存在,把当前事务挂起。
SUPPORTS:支持使用当前事务,如果当前事务不存在,则不使用事务。
NOT_SUPPORTED:无事务执行,如果当前事务存在,把当前事务挂起。
MANDATORY:中文翻译为强制,支持使用当前事务,如果当前事务不存在,则抛出Exception。
NEVER:无事务执行,如果当前有事务则抛出Exception。
NESTED:嵌套事务,如果当前事务存在,那么在嵌套的事务中执行。如果当前事务不存在,则表现跟REQUIRED一样。
注解配置时如:@Transactional(propagation=Propagation.REQUIRED)
注意
事务调用只能作用于当前方法,所以对应的事务传播机制要在对应的方法上标明。
当前事务存在
主方法可认为是产生当前事务的方法(此处不讨论多重调用的事务,原理是一样的);
次方法则指带有对应传播机制的方法
传播机制 | 主方法异常 | 次方法异常 |
---|---|---|
REQUIRED | 全失败 | 全失败 |
REQUIRES_NEW | 只有次方法的insert成功 | 全失败 |
SUPPORTS | 全失败 | 全失败 |
NOT_SUPPORTED | 只有次方法的insert成功 | 只有次方法的insert成功 |
MANDATORY | 全失败 | 全失败 |
NEVER | Existing transaction found | Existing transaction found |
NESTED | 全失败 | 全失败 |
当前事务不存在
当前事务不存在的情况下主方法的insert必然成功的,所以只需要考虑次方法是否成功了
传播机制 | 次方法异常 |
---|---|
REQUIRED | 失败 |
REQUIRES_NEW | 失败 |
SUPPORTS | 成功 |
NOT_SUPPORTED | 成功 |
MANDATORY | No existing transaction found |
NEVER | 成功 |
NESTED | 失败 |
表格比较
以上DEMO可以看出NESTED 和REQUIRED 作用非常类似,于是我继续查询资料得知NESTED 是增加了一个savepoint,我们可以使用try…catch…捕捉到异常来处理从而无需回滚之前的修改。
测试try_catch
尝试除了never的次方法异常主方法使用try_catch时的情况
传播机制 | 次方法异常 |
---|---|
REQUIRED | Transaction rolled back because it has been marked as rollback-only |
REQUIRES_NEW | 只有主方法成功,次方法报错 |
SUPPORTS | Transaction rolled back because it has been marked as rollback-only |
NOT_SUPPORTED | 全成功 |
MANDATORY | Transaction rolled back because it has been marked as rollback-only |
NESTED | 主方法成功 |
总结
若存在当前事务
- 同一事务的REQUIRED 、SUPPORTS 、MANDATORY的次方法出现异常时,事务就会被标记为 rollback-only ;因此就算主方法catch到处理掉也只能回滚;
- 而同一事务的NESTED的次方法保存了savepoint,catch处理掉异常就能继续执行主方法了;
- REQUIRES_NEW、NOT_SUPPORTED的次方法则是挂起了当前事务,故他们就算出现异常处理掉就不会影响当前事务了;
可能使用同一事务的传播机制区别
- REQUIRED、SUPPORTS都能继承当前事务的,区别在于前者没有当前事务的时候会创建一个,后者则不会;
- MANDATORY则是要求必须要给它一个当前事务,它不会产生;
挂起当前事务两者的区别
- REQUIRES_NEW是会创建一个自己的新事务的;
- NOT_SUPPORTED则简单,它不用事务