事务的传播行为 请用java代码举例说明

发布于:2025-02-11 ⋅ 阅读:(40) ⋅ 点赞:(0)

事务的传播行为(Propagation)定义了一个事务方法在被调用时如何与已有的事务进行交互。Spring 提供了多种传播行为,常用的包括 PROPAGATION_REQUIREDPROPAGATION_REQUIRES_NEWPROPAGATION_NESTED 等。每种传播行为的含义略有不同,具体表现为方法如何参与事务的传播。

下面通过 Java 代码示例来展示几种常见的事务传播行为的使用。

1. PROPAGATION_REQUIRED(默认行为)

PROPAGATION_REQUIRED 是最常用的事务传播行为,表示如果当前没有事务,则新建一个事务;如果当前存在事务,则加入到该事务中。

@Service
public class UserService {

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        // 执行数据库操作
        System.out.println("Executing methodA");
        // 调用methodB,它会加入到当前的事务中
        methodB();
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodB() {
        // 执行数据库操作
        System.out.println("Executing methodB");
    }
}

解释

  • methodA 被 @Transactional(propagation = Propagation.REQUIRED) 注解标注,表示它会在当前事务中执行。如果当前没有事务,它会创建一个新事务。
  • methodA 内部调用了 methodBmethodB 也使用了 @Transactional(propagation = Propagation.REQUIRED) 注解,因此 methodB 会加入到 methodA 的事务中,而不会开启一个新事务。

2. PROPAGATION_REQUIRES_NEW

PROPAGATION_REQUIRES_NEW 表示无论当前是否有事务,都会新建一个事务,且当前事务会被挂起,直到新事务完成后才会恢复。

@Service
public class UserService {

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        // 执行数据库操作
        System.out.println("Executing methodA");
        // 调用methodB,它会新建一个事务
        methodB();
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void methodB() {
        // 执行数据库操作
        System.out.println("Executing methodB in a new transaction");
    }
}

解释

  • methodA 使用了 Propagation.REQUIRED,所以它会在当前事务中执行。
  • methodB 使用了 Propagation.REQUIRES_NEW,所以它会启动一个新的事务,并挂起当前的事务。methodA 会等待 methodB 完成,之后继续执行。

3. PROPAGATION_NESTED

PROPAGATION_NESTED 表示如果当前存在事务,则嵌套一个事务;如果当前没有事务,则与 REQUIRED 行为一致,创建一个新事务。嵌套事务支持回滚仅对当前嵌套的事务,不会影响外部事务。

@Service
public class UserService {

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        // 执行数据库操作
        System.out.println("Executing methodA");
        // 调用methodB,它会嵌套一个事务
        methodB();
    }

    @Transactional(propagation = Propagation.NESTED)
    public void methodB() {
        // 执行数据库操作
        System.out.println("Executing methodB in a nested transaction");
        // 模拟抛出异常,回滚methodB的事务,但不会影响methodA
        throw new RuntimeException("Exception in methodB");
    }
}

解释

  • methodA 使用 Propagation.REQUIRED,在外部事务中执行。
  • methodB 使用 Propagation.NESTED,会在当前的事务中启动一个嵌套事务。如果 methodB 抛出异常,只有 methodB 的事务会回滚,methodA 的事务(外部事务)则不会受到影响。

4. PROPAGATION_SUPPORTS

PROPAGATION_SUPPORTS 表示如果当前存在事务,则加入到该事务中;如果没有事务,则以非事务的方式执行。

@Service
public class UserService {

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        // 执行数据库操作
        System.out.println("Executing methodA");
        // 调用methodB,它不会开启新的事务,如果没有事务会以非事务方式执行
        methodB();
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public void methodB() {
        // 执行数据库操作
        System.out.println("Executing methodB with SUPPORTS propagation");
    }
}

解释

  • methodA 使用 Propagation.REQUIRED,如果当前没有事务,它会新建一个事务。
  • methodB 使用 Propagation.SUPPORTS,如果当前有事务,methodB 会加入到该事务中。如果当前没有事务,则 methodB 会以非事务的方式执行。

5. PROPAGATION_MANDATORY

PROPAGATION_MANDATORY 表示当前方法必须在一个已经存在的事务中执行,如果当前没有事务,抛出异常。

@Service
public class UserService {

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        // 执行数据库操作
        System.out.println("Executing methodA");
        // 调用methodB,methodB必须在一个已存在的事务中执行
        methodB();
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public void methodB() {
        // 执行数据库操作
        System.out.println("Executing methodB with MANDATORY propagation");
    }
}

解释

  • methodA 使用 Propagation.REQUIRED,因此它可以开启一个新的事务或加入到现有事务中。
  • methodB 使用 Propagation.MANDATORY,这意味着它必须在一个已经存在的事务中执行。如果没有事务,methodB 会抛出异常。

6. PROPAGATION_NEVER

PROPAGATION_NEVER 表示当前方法不能在事务中执行,如果当前有事务,抛出异常。

@Service
public class UserService {

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        // 执行数据库操作
        System.out.println("Executing methodA");
        // 调用methodB,methodB不能在事务中执行
        methodB();
    }

    @Transactional(propagation = Propagation.NEVER)
    public void methodB() {
        // 执行数据库操作
        System.out.println("Executing methodB with NEVER propagation");
    }
}

解释

  • methodA 使用 Propagation.REQUIRED,如果当前没有事务,它会新建一个事务。
  • methodB 使用 Propagation.NEVER,这表示 methodB 不能在事务中执行。如果当前有事务,methodB 会抛出异常。

总结

Spring 的事务传播行为可以用来控制方法如何参与已有的事务,具体的传播行为决定了事务的启动、挂起、嵌套等特性。通过合理选择传播行为,可以实现不同的事务管理策略,适应不同的业务需求。

常用的事务传播行为:

  • PROPAGATION_REQUIRED: 默认行为,支持当前事务或创建新事务。
  • PROPAGATION_REQUIRES_NEW: 创建新事务,挂起当前事务。
  • PROPAGATION_NESTED: 嵌套事务,支持事务回滚。
  • PROPAGATION_SUPPORTS: 如果当前有事务,则加入当前事务;如果没有事务,则以非事务方式执行。
  • PROPAGATION_MANDATORY: 必须在当前事务中执行,否则抛出异常。
  • PROPAGATION_NEVER: 不能在事务中执行,如果有事务则抛出异常。

网站公告

今日签到

点亮在社区的每一天
去签到