spring事务传播方式整理
参考地址:https://www.cnblogs.com/chenhuadong12/p/14411254.html
1、传播特性定义
PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 PROPAGATION_REQUIRED 类似的操作。
NESTED:如果业务方法在一个事务中执行,就在这个事务中嵌套,如果没有事务按着required执行,开启单独的事务,这种事务有多个事务的保存点,内部事务的回滚对外部事务没有影响
2、REQUIRED和NESTED回滚的区别
两种方式区别,最大的问题在于保存点的设置,很多同学会认为内部设置REQUIRED和NESTED效果是一样的,其实在外层方法对内层方法的异常情况在进行捕获的时候区别很大,两者报的异常信息都不同,使用REQUIRED的时候,会报Transaction rolled back because it has been marked as rollback-only信息,因为内部异常了,设置了回滚标记,外部捕获之后,要进行事务的提交,此时发现有回滚标记,那么意味着要回滚,所以会报异常,而NESTED不会发证这种情况,因为在回滚的时候把回滚标记清除了,外部捕获异常后去提交,没发现回滚标记,就可以正常提交了。
3、REQUIRED_NEW和REQUIRED区别
这两种方式产生的效果是一样的,但是REQUIRED_NEW会有新的连接生成,而NESTED使用的是当前事务的连接,而且NESTED还可以回滚到保存点,REQUIRED_NEW每次都是一个新的事务,没有办法控制其他事务的回滚,但NESTED其实是一个事务,外层事务可以控制内层事务的回滚,内层就算没有异常,外层出现异常,也可以全部回滚。
外层事务传播特性 | 内层事务传播特性 | 执行情况 |
PROPAGATION_REQUIRED
|
1、PROPAGATION_REQUIRED 2、PROPAGATION_SUPPORTS |
内层事务不会提交,在外层事务中统一进行事务提交,如果内层事务或者外层事务中出现异常情况,那么会在外层事务处理中统一进行异常回滚 |
4、PROPAGATION_NEVER |
外层方法不能出现事务,如果出现事务直接报错 | |
5、PROPAGATION_NOT_SUPPORTED |
外层方法有事务直接挂起,内层没有异常情况直接执行,如果内层有方法异常,那么内层方法中已经执行的数据库操作不会触发回滚,而外层的事务方法会进行回滚操作,同样如果外层方法出现了异常操作,那么内部方法是不会回滚的,只有外部事务才会回滚 |
|
6、PROPAGATION_REQUIRES_NEW | 如果外层方法中存在事务,内层方法在运行的时候会挂起外层事务并开启一个新的事务,如果程序正常执行,则内层方法优先事务提交,然后外层事务再提交,如果内层方法存在异常,内层事务会优先回滚,外层事务也会回滚,如果外层方法中存在异常,那么内层事务正常提交,外层事务进行回滚操作 | |
7、 PROPAGATION_NESTED |
1、 如果外层方法中有事务,那么直接创建一个保存点,后续操作如果没有异常情况那么会清除保存点信息,并且在外层事务中进行提交操作。 2、如果内层方法中存在异常情况,那么会回滚到保存点,外层方法事务会直接进行回滚 |
|
PROPAGATION_SUPPORTS |
PROPAGATION_REQUIRED |
外层方法不包含事务,所以内层方法会新建一个事物,如果程序正常执行,那么事务正常提交,如果内层方法中出现异常,则内层方法事务正常回滚,外层不做任何处理,如果外层方法出现异常,则内层方法事务正常提交,外层方法抛出异常 |
PROPAGATION_SUPPORTS PROPAGATION_NEVER PROPAGATION_NOT_SUPPORTED |
内外层方法都不包含事务的话,会以无事务的方法开始运行,每个数据库操作直接执行即可,如果出现异常情况,则后续的操作不会执行,但已经执行过的数据库操作不受影响 | |
PROPAGATION_MANDATORY | 外层方法中如果不包含事务的话,那么内层方法在获取事务对象的时候直接报错,而外层方法中不包含事务,所以无需回滚。 | |
PROPAGATION_NESTED | 外层方法不包含事务,所以内层方法会新建一个事务,如果程序正常执行那么事务会正常提交, 如果内层方法出现异常,则内层事务正常回滚,而外层事务不做任何处理,如果外层方法出现异常,则内层方法事务正常提交,外层方法抛出异常。 |
|
PROPAGATION_MANDATORY |
1、PROPAGATION_REQUIRED 2、PROPAGATION_SUPPORTS 3、PROPAGATION_MANDATORY 5、 PROPAGATION_NOT_SUPPORTED |
PROPAGATION_MANDATORY 不可以作为外层事务,在运行的时候必须需要一个事物 |
PROPAGATION_NEVER | ||
PROPAGATION_NOT_SUPPORTED | ||
PROPAGATION_REQUIRES_NEW |
1、PROPAGATION_REQUIRED 2、PROPAGATION_SUPPORTS 3、PROPAGATION_MANDATORY |
内层事务不会提交,在外层事务中统一进行事务提交,如果内层事务或者外层事务中出现异常情况,那么会在外层事务处理中统一进行异常回滚 |
4、PROPAGATION_NEVER | 外层方法不能出现事务,如果出现事务则直接报错 | |
5、PROPAGATION_NOT_SUPPORTED |
外层方法有事务直接挂起,内层没有异常情况直接执行,如果内层有方法异常,那么内层方法中已经执行的数据库操作不会触发回滚,而外层的事务方法会进行回滚操作,同样如果外层方法出现了异常操作,那么内部方法是不会回滚的,只有外部事务才会回滚 |
|
6、PROPAGATION_REQUIRES_NEW |
如果外层方法中存在事务,内层方法在运行的时候会挂起外层事务并开启一个新的事务,如果程序正常执行,则内层方法优先事务提交,然后外层事务再提交,如果内层方法存在异常,内层事务会优先回滚,外层事务也会回滚,如果外层方法中存在异常,那么内层事务正常提交,外层事务进行回滚操作 |
|
7、 PROPAGATION_NESTED |
1、 如果外层方法中有事务,那么直接创建一个保存点,后续操作如果没有异常情况那么会清除保存点信息,并且在外层事务中进行提交操作。 2、如果内层方法中存在异常情况,那么会回滚到保存点,外层方法事务会直接进行回滚 3、如果外层方法中存在异常情况,那么内层方法会正常执行,并且执行完毕之后释放保存点,并且外层方法事务会进行回滚 |
|
PROPAGATION_NESTED |