问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

详细解释Spring事务的传播机制

创作时间:
作者:
@小白创作中心

详细解释Spring事务的传播机制

引用
CSDN
1.
https://blog.csdn.net/kaka_buka/article/details/140010482

Spring框架中的事务传播机制定义了在一个事务方法调用另一个事务方法时,Spring如何管理这些方法之间的事务边界。Spring提供了七种事务传播行为,每种行为都有其特定的适用场景。本文将详细解释这七种传播行为,并通过代码示例帮助读者理解它们的特点和使用场景。

1. PROPAGATION_REQUIRED

这是最常用的事务传播行为。如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这种行为确保所有事务操作都在一个统一的事务上下文中执行。

适用场景 :大多数情况下使用此传播行为,确保多个事务操作在同一个事务中执行,以保持数据一致性。

什么情况下当前会没有事务?当前是指什么?

在讨论Spring事务传播行为时,“当前”指的是方法执行的上下文,即方法被调用的时刻。当前是否存在事务取决于调用链上的事务配置和执行状态。以下是一些常见情况下当前没有事务的情形:

  1. 外层方法没有事务管理 :如果调用事务方法的外层方法没有被事务注解(如@Transactional)标记,那么在调用事务方法时,当前就没有事务存在。

  2. 事务已经提交或回滚 :如果前一个事务操作已经完成(提交或回滚),当前就没有活跃的事务。

  3. 非事务调用 :从非事务管理的代码路径调用事务方法。例如,从普通的Java方法或第三方库代码中调用事务方法。

  4. 不支持事务的方法 :有些方法或组件不支持事务管理,在这些方法中调用事务方法时,当前没有事务。

举例说明

假设有两个方法 methodAmethodB,其中 methodB 被标记为 @Transactional

public class MyService {
    
    public void methodA() {
        // methodA没有事务管理
        methodB();
    }

    @Transactional
    public void methodB() {
        // methodB有事务管理
        // 执行数据库操作
    }
}

在这种情况下,调用 methodA 时:

  • methodA 没有事务管理,因此当前没有事务。
  • methodA 调用 methodB 时,由于 methodA 没有事务,所以 methodB 会创建一个新的事务。

如果将 methodA 也标记为 @Transactional

@Transactional
public void methodA() {
    methodB();
}

此时,调用 methodA 时:

  • methodA 开启了一个事务,因此当前有事务。
  • methodA 调用 methodB 时,methodB 会加入 methodA 的事务,而不是创建新的事务。

如果methodA没有事务,调用了有事务的methodB,那么methodB执行之后的部分,也在事务当中吗?

如果 methodA 没有事务,而调用了有事务的 methodB,那么 methodB 执行之后的部分,不会在事务当中。具体来说,事务的范围仅限于 methodB 的执行过程,methodB 方法返回后,事务就会结束。

下面通过一个具体的例子来说明这个过程:

假设有以下两个方法:

public class MyService {
    
    public void methodA() {
        // 非事务代码
        methodB(); // 调用有事务管理的方法
        // 继续执行非事务代码
    }

    @Transactional
    public void methodB() {
        // 有事务管理的代码
        // 执行数据库操作
    }
}

调用 methodA 时的事务行为如下:

  1. methodA 开始执行,此时没有事务。
  2. methodA 调用 methodB,由于 methodB 被标记为 @Transactional,Spring 会为 methodB 创建一个新的事务。
  3. methodB 在事务中执行其代码(如数据库操作)。
  4. methodB 执行完成后,事务提交或回滚(取决于方法执行的结果和异常情况)。
  5. methodB 返回到 methodA,此时事务已经结束。
  6. methodA 继续执行剩余代码,但此时已经没有事务。

所以,在 methodA 中,methodB 执行的部分是在事务中的,但 methodB 返回后,methodA 剩余的代码是不在事务中的。事务边界由 methodB 的开始和结束决定,事务结束后事务上下文不再存在。

举例:

public class MyService {
    
    public void methodA() {
        System.out.println("methodA: start");
        methodB();
        System.out.println("methodA: end");
    }

    @Transactional
    public void methodB() {
        System.out.println("methodB: in transaction");
        // 这里执行一些数据库操作
    }
}

运行结果:

methodA: start
methodB: in transaction
methodA: end

在这个示例中:

  • “methodA: start” 和 “methodA: end” 的打印是在没有事务的情况下进行的。
  • “methodB: in transaction” 的打印和数据库操作是在事务中的。

这样可以看出,methodB 的事务边界不影响 methodA 的事务状态。

2. PROPAGATION_REQUIRES_NEW

总是启动一个新的事务。如果当前存在事务,则将当前事务挂起。在新的事务执行完成后,恢复先前的事务。

适用场景 :适用于需要独立事务的情况,例如记录日志或审计信息,不希望这些操作受到主事务的影响。

3. PROPAGATION_SUPPORTS

支持当前事务。如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。

适用场景 :适用于既能在事务内执行,也能在事务外执行的操作。比如,某些只读操作或性能要求不高的操作。

4. PROPAGATION_NOT_SUPPORTED

以非事务方式执行操作。如果当前存在事务,则将当前事务挂起。

适用场景 :适用于不需要事务支持的操作,或某些性能要求高、不希望受到事务管理开销影响的操作。

5. PROPAGATION_NEVER

以非事务方式执行。如果当前存在事务,则抛出异常。

适用场景 :适用于明确不希望在事务中执行的操作。比如,某些数据库操作可能不支持事务。

6. PROPAGATION_MANDATORY

支持当前事务。如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。

适用场景 :适用于必须在现有事务中执行的操作。通常用于一些关键业务逻辑,要求调用者必须在事务中运行。

7. PROPAGATION_NESTED

如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则创建一个新的事务。嵌套事务依赖于底层数据库对保存点(savepoint)的支持。

适用场景 :适用于需要部分提交或回滚的复杂业务操作。比如,复杂的财务操作,某些步骤失败后需要回滚到特定点。

本文原文来自CSDN

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号