Spring事务的传播属性

mac2022-06-30  103

所谓Spring事务的传播属性,就是定义在存在多个事务同时存在的时候,Spring应该如何处理这些事务的行为。这些属性在TransactionDefinition中定义,具体常量的解释见下表:

常量名称常量解释PROPAGATION_REQUIRED

支持当前事务。

如果当前有事务,则加入当前事务;如果当前没有事务,就新建一个事务。

这是最常见的选择,也是 Spring 事务默认的传播属性。

PROPAGATION_REQUIRES_NEW

新建事务。

即使当前有事务,会额外新建一个事务,新建的事务和原事务相互独立,互不影响。

PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。PROPAGATION_MANDATORY支持当前事务,如果当前没有事务,就抛出异常。PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常。PROPAGATION_NESTED

嵌套事务。

将创建一个依赖于外层事务的子事务,子事务的提交与回滚由外层事务控制,但它无法影响外层事务。当外层事务提交或回滚时,子事务也会连带提交和回滚。

具体场景:

假设外层事务 ServiceA 的 methodA() 调用内层 ServiceB 的 methodB()

1、PROPAGATION_REQUIRED

如果serviceA.methodA()与serviceB.methodB()的事务传播属性都定义为PROPAGATION_REQUIRED,Spring会在serviceA.methodA()执行时开启事务,当调用serviceB.methodB()时,会将methodB加入到methodA的事务中,这样两者都在同一个事务下工作,无论methodA还是methodB出现异常,整个事务都会回滚。

2、PROPAGATION_REQUIRES_NEW

如果serviceA.methodA() 为PROPAGATION_REQUIRED,serviceB.methodB() 为PROPAGATION_REQUIRES_NEW,当methodA()开始调用methodB()时,methodA()所在的事务就会挂起,methodB()会开启一个新事务,等methodB()的事务完成以后,methodA()才会继续执行。两者的事务相互独立,互不影响。

3、PROPAGATION_NESTED

如果serviceA.methodA() 为PROPAGATION_REQUIRED,serviceB.methodB() 为PROPAGATION_NESTED,执行逻辑如下:

void methodA() { try{ serviceB.methodB(); } catch(Exception e) { // 执行异常情况下的业务逻辑 } // methodA的相关业务处理 }

当service.methodB()方法出现异常时,methodB的异常会被最外层的methodA捕获,并执行后序的异常处理逻辑以及methodA自身的业务逻辑,最终methodA的事务会正常提交,而methodB的事务会被回滚。

如果methodB正常执行,而后续methodA出现异常,那么methodA和methodB都会回滚。

这就是嵌套事务独有的特性,内层事务的提交与回滚都取决于外层事务。

PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大区别在于:PROPAGATION_REQUIRES_NEW 将创建一个全新的事务,它和外层事务没有任何关系,而PROPAGATION_NESTED 将创建一个依赖于外层事务的子事务,当外层事务提交或回滚时,子事务也会连带提交和回滚。

其它传播属性不是很常用,这里不过多讨论了。

 

最新回复(0)