3.4 Spring事务传播机制
Spring事务传播机制主要定义了7种类型,分别是REQUIRED、SUPPORTS、MAND-ATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED,如表3-1所示。
表3-1 Spring事务传播机制类型分类
本节将对这些事务传播机制的类型进行简单的介绍。
3.4.1 7种事务传播机制类型
Spring中事务传播机制的类型是通过枚举的方式定义的,源码在org.springframework.transaction.annotation.Propagation枚举类中,如下所示。
package org.springframework.transaction.annotation; import org.springframework.transaction.TransactionDefinition; public enum Propagation { REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED), SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS), MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY), REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW), NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED), NEVER(TransactionDefinition.PROPAGATION_NEVER), NESTED(TransactionDefinition.PROPAGATION_NESTED); private final int value; Propagation(int value) { this.value = value; } public int value() { return this.value; } }
通过枚举类Propagation的源码可以看出,Propagation类中的每个枚举项都与Transaction-Definition接口中定义的常量相对应。再来看下TransactionDefinition接口中定义的常量,如下所示。
package org.springframework.transaction; import java.sql.Connection; public interface TransactionDefinition { int PROPAGATION_REQUIRED = 0; int PROPAGATION_SUPPORTS = 1; int PROPAGATION_MANDATORY = 2; int PROPAGATION_REQUIRES_NEW = 3; int PROPAGATION_NOT_SUPPORTED = 4; int PROPAGATION_NEVER = 5; int PROPAGATION_NESTED = 6; int ISOLATION_DEFAULT = -1; int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED; int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED; int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ; int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE; ##########################省略部分代码######################## }
在TransactionDefinition接口中定义的ISOLATION_READ_UNCOMMITTED、ISOLA-TION_READ_COMMITTED、ISOLATION_REPEATABLE_READ、ISOLATION_SERIALI-ZABLE事务传播类型和JDBC中的事务传播类型相对应。
这里需要说明的是,枚举类Propagation结合@Transactional注解使用,枚举类中定义的事务传播行为类型与TransactionDefinition接口中定义的事务传播类型相对应。在使用@Transactional注解时,使用的是Propagation枚举类中的事务传播类型,而不是直接使用TransactionDefinition接口中定义的事务传播类型。
1.REQUIRED事务传播类型
REQUIRED事务传播类型表示如果当前没有事务,就创建一个事务,如果已经存在一个事务,就加入这个事务。这是最常见的事务传播类型,也是Spring当中默认的事务传播类型。外部不存在事务时,开启新的事务,外部存在事务时,将其加入外部事务中。如果调用端发生异常,则调用端和被调用端的事务都将回滚。
在这种事务传播类型下,当前操作必须在一个事务中执行。
REQUIRED事务传播类型在Propagation枚举类中的源码如下所示。
REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED)
基本用法的代码片段如下所示。
@Transactional(propagation=Propagation.REQUIRED)
2.REQUIRES_NEW事务传播类型
REQUIRES_NEW事务传播类型表示如果当前存在事务,则把当前事务挂起,并重新创建新的事务并执行,直到新的事务提交或者回滚,才会恢复执行原来的事务。这种事务传播类型具备隔离性,将原有事务和新创建的事务隔离,原有事务和新创建的事务的提交和回滚互不影响。新创建的事务和被挂起的事务没有任何关系,它们是两个不相干的独立事务。外部事务执行失败后回滚,不会回滚内部事务的执行结果。内部事务执行失败抛出异常,被外部事务捕获到时,外部事务可以不处理内部事务的回滚操作。
REQUIRES_NEW事务传播类型在Propagation枚举类中的源码如下所示。
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW)
基本用法的代码片段如下所示。
@Transactional(propagation=Propagation.REQUIRES_NEW)
3.SUPPORTS事务传播类型
SUPPORTS事务传播类型表示支持当前事务,如果当前没有事务,就以非事务的方式执行。外部不存在事务时,不会开启新的事务,外部存在事务时,将其加入外部事务。
SUPPORTS事务传播类型在Propagation枚举类中的源码如下所示。
SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS)
基本用法的代码片段如下所示。
@Transactional(propagation=Propagation.SUPPORTS)
4.MANDATORY事务传播类型
MANDATORY事务传播类型表示支持当前事务,这种事务传播类型具备强制性,当前操作必须存在事务,如果不存在,则抛出异常。
MANDATORY事务传播类型在Propagation枚举类中的源码如下所示。
MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY)
基本用法的代码片段如下所示。
@Transactional(propagation=Propagation.MANDATORY)
5.NOT_SUPPORTED事务传播类型
NOT_SUPPORTED事务传播类型表示以非事务方式执行,如果当前操作在一个事务中,则把当前事务挂起,直到当前操作完成再恢复事务的执行。如果当前操作存在事务,则把事务挂起,以非事务的方式运行。
NOT_SUPPORTED事务传播类型在Propagation枚举类中的源码如下所示。
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED)
基本用法的代码片段如下所示。
@Transactional(propagation=Propagation.NOT_SUPPORTED)
6.NEVER事务传播类型
NEVER事务传播类型表示以非事务的方式执行,如果当前操作存在事务,则抛出异常。
NEVER事务传播类型和NOT_SUPPORTED事务传播类型的区别是如果当前存在事务,则NEVER事务传播类型会抛出异常,而NOT_SUPPORTED事务传播类型会把当前事务挂起,以非事务的方式执行。NEVER事务传播类型与MANDATORY事务传播类型的区别是NEVER事务传播类型表示如果当前操作存在事务,则抛出异常,而MANDATORY事务传播类型表示如果当前操作不存在事务,则抛出异常。
NEVER事务传播类型在Propagation枚举类中的源码如下所示。
NEVER(TransactionDefinition.PROPAGATION_NEVER)
基本用法的代码片段如下所示。
@Transactional(propagation=Propagation.NEVER)
7.NESTED事务传播类型
NESTED事务传播类型表示如果当前方法有一个事务正在运行,则这个方法应该运行在一个嵌套事务中,被嵌套的事务可以独立于被封装的事务进行提交或者回滚。如果没有活动事务,则按照REQUIRED事务传播类型执行。
如果封装事务存在,并且外层事务抛出异常回滚,那么内层事务必须回滚。如果内层事务回滚,则并不影响外层事务的提交和回滚。如果封装事务不存在,则按照REQUIRED事务传播类型执行。
NESTED事务传播类型在Propagation枚举类中的源码如下所示。
NESTED(TransactionDefinition.PROPAGATION_NESTED)
基本用法的代码片段如下所示。
@Transactional(propagation=Propagation.NESTED)
3.4.2 常用的事务传播类型
虽然Spring提供了7种事务传播机制类型,但是在日常工作中经常使用的只有REQU-IRED、NOT_SUPPORTED和REQUIRES_NEW这3种。
这3种事务传播类型的使用场景如表3-2所示。
表3-2 Spring常用事务传播类型使用场景