上一篇文章中见过了事务的特性以及隔离级别,今天来说一下事务的传播性,事务是一个好东西,但是并不是每一个方法都应该加上事务,在事务的隔离级别中提到过一点:越是严格,耗费的性能越大,那么如果每个方法都加了事务,而不论是否会涉及到数据的修改,那么这就属于事务的滥用了,没起到应有的作用不说,反而还会一点点的拖慢你的系统。
为了应对这一问题,“事务的传播性”这一概念又横空出世了,打个最简单的比方:现在的项目中,大多都分层,controller层 + service层 + dao层,而业务一般都堆积在service层,要么是service调service,要么是service调dao,那么我们的事务一般也都是加在service层的,此时我们并没有给dao层也加上事务,但是却能达到失败回滚的效果,这就是事务的传播性生效了,更通俗点儿的理解就是service层把事务传递给了dao层。
上面举的例子,并不是很难理解,我们现在来看一下Spring事务都有哪些传播性(以方法A调用方法B为例来详解):
PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务;
方法A调用方法B,如果方法A的已经有开启事务了,那么方法B就不会再新开启事务,而是直接使用方法A的事务,不管双方哪一个执行失败,都会一起回滚。
PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起;
方法A调用方法B,就算方法A已经开启了事务,那么方法B也依旧会开启一个新的事务,执行期间将方法A的事务挂起,直到执行完毕之后才开始继续执行方法A,如果方法A执行失败回滚,不会影响到方法B,方法B该提交还是一样提交。
PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行;
此方式比较特殊,是一种随波逐流的方式,如果有它就用,如果没有它就不用。
PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起;
不支持事务,如果方法A已经开启了事务,调用方法B时,会将方法A的事务挂起之后开始执行方法B,执行完毕之后继续执行方法A。
PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常;
强制在一个事务中执行,如果方法A开启了事务,方法B也试图开启一个事务,此时就会直接抛出异常。
PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常;
不支持事务,如果强制开启事务,或者方法A已经开启了事务,再来调用方法B,就会直接抛出异常。
PROPAGATION_NESTED:新建事务,依赖于上级事务,如果失败则一同回滚;
这个事务和requires_new很相似,但是不同点在于事务提交的时候,它会让方法B依赖于方法A的事务,B就算开启了事务,也不会主动提交,而是等待A一起提交,此时如果A报错回滚了,那么B也会一起回滚。
注意:spring事务中,默认是只有运行时异常(RuntimeException及其子类)才会回滚,而且使用的默认传播性是REQUIRED。
转自:不忘初心 https://www.jiweichengzhu.com/article/8488e494ff8e45b58fe3de6821c1b97a
文章评论