spring事务传播7种

1 如何使用

在方法上加Transactional标签 并配置propagation 默认为REQUIRED
@Transactional(propagation = Propagation.REQUIRED)
Propagation 枚举有7种 
    REQUIRED(0),
    SUPPORTS(1),
    MANDATORY(2),
    REQUIRES_NEW(3),
    NOT_SUPPORTED(4),
    NEVER(5),
    NESTED(6);

2 每种意思

枚举小写含义
REQUIREDrequired必须的如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
SUPPORTSsupports支持支持当前事务,如果当前没有事务,就以非事务方式执行。
MANDATORYmandatory强制性的,义务的使用当前的事务,如果当前没有事务,就抛出异常。
REQUIRED NEWrequired new新建事务 挂起当前事务新建事务,如果当前存在事务,把当前事务挂起。
NOT SUPPORTEDnot supports不支持以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
NEVERnever非事务执行 发现事务抛出异常以非事务方式执行,如果当前存在事务,则抛出异常。
NESTEDnested嵌套如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

3 相互关系

A方法调用B方法,AB方法都有事务,并且传播特性不同,那么A如果有异常,B怎么办,B如果有异常,A怎么办?

外层方法事务传播特性内层方法事务传播特性执行情况
REQUIREDMANDATORY如果程序正常执行,那么内层事务不会提交,在外部事务中统一进行事务提交,
如果内层事务,或者外层事务中出现异常情况,那么会在外层事务的处理中统一进行异常回滚
REQUIRED
SUPPORTS
NEVER外层方法不能出现事务,如果出现事务则直接报错
NOT SUPPORTED外层方法中有事务,直接挂起,内层方法没有异常情况的话直接顺利执行,
如果内层方法有异常的话,那么内层方法中已经执行的数据库操作不会触发回滚,
而外层方法的事务会进行回滚操作,同样,如果外层方法中出现了异常操作,
那么内部方法是不会回滚的,只有外层事务才会回滚
REQUIRED NEW如果外层方法中存在事务,内层方法在运行的时候会挂起外层事务并开启一个新的事务,如果程序正常执行,则内层方法优先事务提交,然后外层方法再提交;如果内层方法中存在异常,内层事务会优先回滚,外层方法事务也会回滚,如果外层方法中存在异常,那么内层事务正常正常提交,而外层方法会进行回滚操作
NESTED如果外层方法中有事务,那么直接创建一个保存点,后续操作中如果没有异常情况,
那么会清除保存点信息,并且在外层事务中进行提交操作,
如果内层方法中存在异常情况,那么会回滚到保存点,外层方法事务会直接进行回滚,
如果外层方法中存在异常情况,
那么会内层方法会正常执行,并且执行完毕之后释放保存点,并且外层方法事务会进行回滚
MANDATORYMANDATORYMANDATORY不可以作为外层事务,在运行的时候必须需要一个事务,因此后续的
REQUIRED
SUPPORTS
NEVER
NOT SUPPORTED
REQUIRED NEW
NESTED
SUPPORTSMANDATORY外层方法中如果不包含事务的话,那么内层方法在获取事务对象的时候直接报错,而外层方法中不包含事务,所以无需回滚
REQUIRED外层方法中不包含事务,所以内层方法会新建一个事务,如果程序正常执行,那么事务会正常提交,如果内层方法中出现异常,则内层方法事务正常回滚,而外层事务不做任何处理,如果外层方法中出现异常,则内层方法事务正常提交,外层方法抛出异常
SUPPORTS内外层方法都不包含事务的话,会以无事务的方法开始运行,每个数据库操作直接执行即可,如果出现异常情况,则后续的操作不会执行,但已经执行过的数据库操作不受任何影响
NEVER
NOT SUPPORTED
REQUIRED NEW外层方法中不包含事务,所以内层方法会新建一个事务,如果程序正常执行,那么事务会正常提交,如果内层方法中出现异常,则内层方法事务正常回滚,而外层事务不做任何处理,如果外层方法中出现异常,则内层方法事务正常提交,外层方法抛出异常
NESTED
NEVERMANDATORY外层方法中如果不包含事务的话,那么内层方法在获取事务对象的时候直接报错,而外层方法中不包含事务,所以无需回滚
REQUIRED外层方法中不包含事务,所以内层方法会新建一个事务,如果程序正常执行,那么事务会正常提交,如果内层方法中出现异常,则内层方法事务正常回滚,而外层事务不做任何处理,如果外层方法中出现异常,则内层方法事务正常提交,外层方法抛出异常
SUPPORTS内外层方法都不包含事务的话,会以无事务的方法开始运行,每个数据库操作直接执行即可,如果出现异常情况,则后续的操作不会执行,但已经执行过的数据库操作不受任何影响
NEVER
NOT SUPPORTED
REQUIRED NEW外层方法中不包含事务,所以内层方法会新建一个事务,如果程序正常执行,那么事务会正常提交,如果内层方法中出现异常,则内层方法事务正常回滚,而外层事务不做任何处理,如果外层方法中出现异常,则内层方法事务正常提交,外层方法抛出异常
NESTED
NOT SUPPORTEDMANDATORY外层方法中如果不包含事务的话,那么内层方法在获取事务对象的时候直接报错,而外层方法中不包含事务,所以无需回滚
REQUIRED外层方法中不包含事务,所以内层方法会新建一个事务,如果程序正常执行,那么事务会正常提交,如果内层方法中出现异常,则内层方法事务正常回滚,而外层事务不做任何处理,如果外层方法中出现异常,则内层方法事务正常提交,外层方法抛出异常
SUPPORTS内外层方法都不包含事务的话,会以无事务的方法开始运行,每个数据库操作直接执行即可,如果出现异常情况,则后续的操作不会执行,但已经执行过的数据库操作不受任何影响
NEVER
NOT SUPPORTED
REQUIRED NEW外层方法中不包含事务,所以内层方法会新建一个事务,如果程序正常执行,那么事务会正常提交,如果内层方法中出现异常,则内层方法事务正常回滚,而外层事务不做任何处理,如果外层方法中出现异常,则内层方法事务正常提交,外层方法抛出异常
NESTED
REQUIRED NEWMANDATORY如果程序正常执行,那么内层事务不会提交,在外部事务中统一进行事务提交,如果内层事务,或者外层事务中出现异常情况,那么会在外层事务的处理中统一进行异常回滚
REQUIRED
SUPPORTS
NEVER外层方法不能出现事务,如果出现事务则直接报错
NOT SUPPORTED外层方法中有事务,直接挂起,内层方法没有异常情况的话直接顺利执行,如果内层方法有异常的话,那么内层方法中已经执行的数据库操作不会触发回滚,而外层方法的事务会进行回滚操作,同样,如果外层方法中出现了异常操作,那么内部方法是不会回滚的,只有外层事务才会回滚
REQUIRED NEW如果外层方法中存在事务,内层方法在运行的时候会挂起外层事务并开启一个新的事务,如果程序正常执行,则内层方法优先事务提交,然后外层方法再提交;如果内层方法中存在异常,内层事务会优先回滚,外层方法事务也会回滚,如果外层方法中存在异常,那么内层事务正常正常提交,而外层方法会进行回滚操作
NESTED如果外层方法中有事务,那么直接创建一个保存点,如果外层方法没有事务,那么就创建一个新的事务,后续操作中如果没有异常情况,那么会清除保存点信息,并且在外层事务中进行提交操作,如果内层方法中存在异常情况,那么会回滚到保存点,外层方法事务会直接进行回滚,如果外层方法中存在异常情况,那么会内层方法会正常执行,并且执行完毕之后释放保存点,并且外层方法事务会进行回滚
NESTEDMANDATORY如果程序正常执行,那么内层事务不会提交,在外部事务中统一进行事务提交,如果内层事务,或者外层事务中出现异常情况,那么会在外层事务的处理中统一进行异常回滚
REQUIRED
SUPPORTS
NEVER外层方法不能出现事务,如果出现事务则直接报错
NOT SUPPORTED外层方法中有事务,直接挂起,内层方法没有异常情况的话直接顺利执行,如果内层方法有异常的话,那么内层方法中已经执行的数据库操作不会触发回滚,而外层方法的事务会进行回滚操作,同样,如果外层方法中出现了异常操作,那么内部方法是不会回滚的,只有外层事务才会回滚
REQUIRED NEW如果外层方法中存在事务,内层方法在运行的时候会挂起外层事务并开启一个新的事务,如果程序正常执行,则内层方法优先事务提交,然后外层方法再提交;如果内层方法中存在异常,内层事务会优先回滚,外层方法事务也会回滚,如果外层方法中存在异常,那么内层事务正常正常提交,而外层方法会进行回滚操作
NESTED如果外层方法中有事务,那么直接创建一个保存点,如果外层方法没有事务,那么就创建一个新的事务,后续操作中如果没有异常情况,那么会清除保存点信息,并且在外层事务中进行提交操作,如果内层方法中存在异常情况,那么会回滚到保存点,外层方法事务会直接进行回滚,如果外层方法中存在异常情况,那么会内层方法会正常执行,并且执行完毕之后释放保存点,并且外层方法事务会进行回滚
如果自己动手把每一种情况都演示了,其实挺好理解的,关键是大家舍不舍得花费时间一个一个去验证,在面试过程中,可能会经常问一下两个问题:
1、REQUIRED和NESTED回滚的区别
在回答两种方式区别的时候,最大的问题在于保存点的设置,很多同学会认为内部设置REQUIRED和NESTED效果是一样的,其实在外层方法对内层方法的异常情况在进行捕获的时候区别很大,两者报的异常信息都不同,使用REQUIRED的时候,会报Transaction rolled back because it has been marked as rollback-only信息,因为内部异常了,设置了回滚标记,外部捕获之后,要进行事务的提交,此时发现有回滚标记,那么意味着要回滚,所以会报异常,而NESTED不会发证这种情况,因为在回滚的时候把回滚标记清除了,外部捕获异常后去提交,没发现回滚标记,就可以正常提交了。
2、REQUIRED_NEW和REQUIRED区别
这两种方式产生的效果是一样的,但是REQUIRED_NEW会有新的连接生成,而NESTED使用的是当前事务的连接,而且NESTED还可以回滚到保存点,REQUIRED_NEW每次都是一个新的事务,没有办法控制其他事务的回滚,但NESTED其实是一个事务,外层事务可以控制内层事务的回滚,内层就算没有异常,外层出现异常,也可以全部回滚。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值