事务的传播机制有7种,下面的传播机制都是针对于被调用的方法来说的,理解起来需要想象成两个service,本文的案例主要讲的是传播机制中的PROPAGATION_REQUIRES_NEW和PROPAGATION_NESTED。
(1)PROPAGATION_REQUIRED(默认):支持使用当前事务,如果当前事务不存在,创建一个新事务。
(2)PROPAGATION_SUPPORTS:支持使用当前事务,如果当前事务不存在,则不使用事务。
(3)PROPAGATION_MANDATORY:中文翻译为强制,支持使用当前事务,如果当前事务不存在,则抛出Exception。
(4)PROPAGATION_REQUIRES_NEW(常用):创建一个新事务,如果当前事务存在,把当前事务挂起。
这个方法会独立提交事务,不受调用者的事务影响,父级异常,它也是正常提交。
(5)PROPAGATION_NOT_SUPPORTED:无事务执行,如果当前事务存在,把当前事务挂起。
(6)PROPAGATION_NEVER:无事务执行,如果当前有事务则抛出Exception。
(7)PROPAGATION_NESTED(常用):嵌套事务,如果当前事务存在,那么在嵌套的事务中执行。如果当前事务不存在,则表现跟REQUIRED一样。
如果当前存在事务,它将会成为父级事务的一个子事务,方法结束后并没有提交,只有等父事务结束才提交。
如果当前没有事务,则新建事务。
如果它异常,父级可以捕获它的异常而不进行回滚,正常提交。
但如果父级异常,它必然回滚,这就是和 REQUIRES_NEW 的区别。
下面直接上案例:
A、B都开启了事务,并且事务A里面方法调用了事务B里的方法
在这里让B发生异常,那么最后经过测试A、B都会发生异常,并且回滚(如果A里面对B进行了try-catch,那么还是会都会回滚)
那么怎样实现B发生异常后,回滚了。A不回滚,数据insert成功?(bz在业务需求中遇到过这样的)
解决方法:(1)事务B里面修改传播机制(默认的机制是PROPAGATION_REQUIRED),经过测试以下两种机制都是可以的。
Propagation_requires_new和propagation_nested的区别(重要,比较常用):
前者如果父级发生了异常,则子事务也是正常提交;后者是如何父级发生了异常,则子事务必然发生回滚。
具体使用哪种传播机制,当然还得根据实际的业务场景来决定。