Transactional Propagation详解

发布时间:2023-05-22

一、什么是Transactional Propagation

Transactional Propagation 是 Spring 事务的重要概念之一,主要解决了多个事务方法之间相互调用时事务的传递问题。简单来说,如果一个事务方法 A 中调用了另一个事务方法 B,那么 Transactional Propagation 就是决定了这两个事务方法将如何交互,以及事务该如何传递。事务的传递可以分为多种类型,Spring 提供了多种固定的Propagation属性,用户可以根据自己的需要选择合适的传播方式。

二、Propagation属性介绍

Spring 提供了如下 7 种 Propagation 属性:

  • Propagation.REQUIRED:如果当前方法正在运行在一个事务中,则方法 B 将在这个事务中运行。否则,方法 B 也将启动一个新的事务,并在自己的事务中运行。
  • Propagation.SUPPORTS:如果当前方法正在运行在一个事务中,则方法 B 也将在这个事务中运行。否则,它将以非事务的方式执行。
  • Propagation.MANDATORY:如果当前方法正在运行在一个事务中,则方法 B 将在这个事务中运行。否则,它将抛出异常。
  • Propagation.REQUIRES_NEW:无论当前方法是否在事务中运行,都将为方法 B 开启一个新的事务。
  • Propagation.NOT_SUPPORTED:无论当前方法是否在事务中运行,方法 B 都将以非事务的方式执行。
  • Propagation.NEVER:如果当前方法正在运行在一个事务中,则方法 B 将抛出异常。
  • Propagation.NESTED:如果当前方法正在运行在一个事务中,则方法 B 将在这个事务的嵌套事务中运行。否则,它将启动一个新的事务,并在自己的事务中运行。

三、Propagation属性示例

假设有两个方法 A 和 B,它们都开启了事务。现在我们来看看不同的 Propagation 属性将如何影响它们之间的交互:

1. PROPAGATION_REQUIRED

@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
    // do some database operations
    methodB();
}
@Transactional(propagation = Propagation.REQUIRED)
public void methodB() {
    // do some other database operations
}

如果 methodA 在一个事务中运行,那么 methodB 也将在同一个事务中运行,它们将使用同一个数据库连接。如果 methodA 没有在一个事务中运行,那么 methodB 将使用自己的事务,它将开启一个新的数据库连接。

2. PROPAGATION_SUPPORTS

@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
    // do some database operations
    methodB();
}
@Transactional(propagation = Propagation.SUPPORTS)
public void methodB() {
    // do some other database operations
}

如果 methodA 在一个事务中运行,那么 methodB 也将在同一个事务中运行,它们将使用同一个数据库连接。如果 methodA 没有在一个事务中运行,那么 methodB 将以非事务方式运行,它将使用自己的数据库连接。

3. PROPAGATION_MANDATORY

@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
    // do some database operations
    methodB();
}
@Transactional(propagation = Propagation.MANDATORY)
public void methodB() {
    // do some other database operations
}

如果 methodA 在一个事务中运行,那么 methodB 也将在同一个事务中运行,它们将使用同一个数据库连接。如果 methodA 没有在一个事务中运行,那么 methodB 将抛出异常。

4. PROPAGATION_REQUIRES_NEW

@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
    // do some database operations
    methodB();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
    // do some other database operations
}

无论 methodA 是否在一个事务中运行,methodB 都将开启一个新的独立事务,它们将使用不同的数据库连接。

5. PROPAGATION_NOT_SUPPORTED

@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
    // do some database operations
    methodB();
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void methodB() {
    // do some other database operations
}

如果 methodA 在一个事务中运行,那么 methodB 将以非事务方式运行,它将使用自己的数据库连接。如果 methodA 没有在一个事务中运行,那么 methodB 也将以非事务方式运行,它将使用自己的数据库连接。

6. PROPAGATION_NEVER

@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
    // do some database operations
    methodB();
}
@Transactional(propagation = Propagation.NEVER)
public void methodB() {
    // do some other database operations
}

如果 methodA 在一个事务中运行,那么 methodB 将抛出异常。如果 methodA 没有在一个事务中运行,那么 methodB 将以非事务方式运行,它将使用自己的数据库连接。

7. PROPAGATION_NESTED

@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
    // do some database operations
    methodB();
}
@Transactional(propagation = Propagation.NESTED)
public void methodB() {
    // do some other database operations
}

如果 methodA 在一个事务中运行,那么 methodB 将在该事务的嵌套事务中运行,它们将使用同一个数据库连接。如果 methodA 没有在一个事务中运行,那么 methodB 将开启一个新的独立事务,它将使用自己的数据库连接。

四、小结

Transactional Propagation 在 Spring 事务中是非常重要的一部分,它决定了不同事务方法之间的交互方式,以及事务该如何传递。Spring 提供了 7 种 Propagation 属性,用户可以根据自己的需要选择合适的传播方式。当我们理解了这些 Propagation 属性的含义和影响后,我们就可以更好地设计我们的事务系统,确保数据的完整性和一致性。