深入理解分布式事务:原理与实战
上QQ阅读APP看书,第一时间看更新

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常用事务传播类型使用场景