您现在的位置是:首页 >学无止境 >springboot的事务传播机制网站首页学无止境

springboot的事务传播机制

ant-老狼 2025-02-17 12:01:03
简介springboot的事务传播机制

Spring Boot 中的事务传播机制用于处理多个事务方法之间相互调用时的事务行为,确保数据的完整性和一致性

传播行为介绍

传播行为描述
Propagation.REQUIRED默认值。如果当前存在事务,则加入该事务;如果不存在事务,则创建一个新事务。
Propagation.SUPPORTS如果当前存在事务,则加入该事务;如果不存在事务,则以非事务方式运行。
Propagation.MANDATORY如果当前存在事务,则加入该事务;如果不存在事务,则抛出异常。
Propagation.REQUIRES_NEW创建一个新事务,如果当前存在事务,则将当前事务挂起。
Propagation.NOT_SUPPORTED以非事务方式运行,如果当前存在事务,则将当前事务挂起。
Propagation.NEVER以非事务方式运行,如果当前存在事务,则抛出异常。
Propagation.NESTED如果当前存在事务,则创建一个嵌套事务;如果不存在事务,则等价于 Propagation.REQUIRED。

说明

假设有两个方法 A 和 B,其中 A 调用了 B,并且它们都使用了 @Transactional 注解,以下是不同传播行为下的事务处理方式:
Propagation.REQUIRED:如果 A 有事务,B 将使用 A 的事务;如果 A 没有事务,B 将创建一个新事务。
Propagation.SUPPORTS:如果 A 有事务,B 将加入 A 的事务;如果 A 没有事务,B 将以非事务方式运行。
Propagation.MANDATORY:如果 A 没有事务,B 将抛出异常。
Propagation.REQUIRES_NEW:无论 A 是否有事务,B 都将创建一个新事务,并将 A 的事务挂起。
Propagation.NOT_SUPPORTED:无论 A 是否有事务,B 都将以非事务方式运行,并将 A 的事务挂起。
Propagation.NEVER:如果 A 有事务,B 将抛出异常;否则 B 以非事务方式运行。
Propagation.NESTED:如果 A 有事务,B 将创建一个嵌套事务;如果 A 没有事务,B 将创建一个新事务。
使用场景
Propagation.REQUIRED:适用于大多数场景,确保方法调用链中的事务一致性。
Propagation.SUPPORTS:适用于读操作,减少事务开销。
Propagation.REQUIRES_NEW:适用于需要独立事务的场景,例如日志记录。
Propagation.NESTED:适用于需要嵌套事务的场景,例如复杂的业务流程。
通过合理选择事务传播行为,可以更好地控制事务的边界和行为,确保应用程序的事务管理更加灵活和高效。

示例

在 Spring Boot 中,可以通过在方法上使用 @Transactional 注解来设置事务传播行为。@Transactional 注解提供了多个属性用于配置事务,其中 propagation 属性用于指定事务传播行为。
设置事务传播行为的步骤

1. 添加 @Transactional 注解

在需要管理事务的方法上添加 @Transactional 注解,并通过 propagation 属性指定传播行为。

2. 指定传播行为

propagation 属性的值是 Propagation 枚举类型,可以选择以下值之一:
Propagation.REQUIRED(默认值)
Propagation.SUPPORTS
Propagation.MANDATORY
Propagation.REQUIRES_NEW
Propagation.NOT_SUPPORTED
Propagation.NEVER
Propagation.NESTED

3. 示例代码

以下是一个示例代码,展示如何设置不同的事务传播行为:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class MyService {

    @Autowired
    private AnotherService anotherService;

    // 默认传播行为 REQUIRED
    @Transactional
    public void methodA() {
        // 业务逻辑
        anotherService.methodB();
    }

    // 指定传播行为 REQUIRES_NEW
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void methodC() {
        // 业务逻辑
    }

    // 指定传播行为 SUPPORTS
    @Transactional(propagation = Propagation.SUPPORTS)
    public void methodD() {
        // 业务逻辑
    }
}

@Service
public class AnotherService {

    @Transactional
    public void methodB() {
        // 业务逻辑
    }
}

事务传播行为的设置示例

  • 示例 1:Propagation.REQUIRED
@Transactional
public void methodA() {
    // 业务逻辑
    anotherService.methodB();
}

如果 methodA 调用时已经存在事务,则 methodB 将加入该事务。
如果 methodA 调用时没有事务,则会创建一个新事务。

  • 示例 2:Propagation.REQUIRES_NEW
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodC() {
    // 业务逻辑
}

无论调用 methodC 时是否存在事务,都会创建一个新事务,并将当前事务挂起。
示例 3:Propagation.SUPPORTS

@Transactional(propagation = Propagation.SUPPORTS)
public void methodD() {
    // 业务逻辑
}

如果调用 methodD 时存在事务,则加入该事务。
如果调用 methodD 时没有事务,则以非事务方式运行。
注意事项
方法调用方式:

  • 事务传播行为只在通过代理调用时生效。如果在同一个类的内部调用被 @Transactional 注解的方法,事务传播行为不会生效。
  • 确保通过 Spring 代理调用事务方法,例如通过注入的 Bean 调用。
    异常处理
  • 默认情况下,运行时异常会回滚事务,而检查型异常不会回滚事务。
  • 可以通过 @Transactional 注解的 rollbackFor 和 noRollbackFor 属性自定义异常处理规则。
    嵌套事务
  • Propagation.NESTED 依赖于数据库的事务支持。如果数据库不支持嵌套事务(如 MySQL 默认的 - - InnoDB 存储引擎),则 Propagation.NESTED 会退化为 Propagation.REQUIRED。

异常处理

在 Spring Boot 中,事务回滚规则可以通过 @Transactional 注解的 rollbackFor 和 noRollbackFor 属性来配置。这两个属性允许你指定哪些异常会导致事务回滚,哪些异常不会导致事务回滚。

1. rollbackFor 属性

rollbackFor 属性用于指定哪些异常会触发事务回滚。默认情况下,Spring 事务管理器会回滚所有未检查的异常(即继承自 RuntimeException 的异常),但不会回滚检查型异常(即继承自 Exception 但不是 RuntimeException 的异常)。

  • 示例:回滚所有异常
@Transactional(rollbackFor = Exception.class)
public void myMethod() {
    // 业务逻辑
}

在这个例子中,无论是运行时异常(RuntimeException)还是检查型异常(Exception),都会导致事务回滚。

  • 示例:回滚特定异常
@Transactional(rollbackFor = {MyCustomException.class, AnotherException.class})
public void myMethod() {
    // 业务逻辑
}

在这个例子中,只有 MyCustomException 和 AnotherException 会导致事务回滚。

2. noRollbackFor 属性

noRollbackFor 属性用于指定哪些异常不会触发事务回滚。默认情况下,检查型异常不会导致事务回滚,但你可以通过 noRollbackFor 明确指定某些异常不回滚。
示例:不回滚特定异常

@Transactional(noRollbackFor = MyCustomException.class)
public void myMethod() {
    // 业务逻辑
}

在这个例子中,即使抛出了 MyCustomException,事务也不会回滚。

  • 示例:结合 rollbackFor 和 noRollbackFor
@Transactional(rollbackFor = Exception.class, noRollbackFor = MyCustomException.class)
public void myMethod() {
    // 业务逻辑
}

在这个例子中,所有异常都会导致事务回滚,但 MyCustomException 不会导致事务回滚。

3. 配置事务管理器

除了通过 @Transactional 注解配置回滚规则外,你还可以在 Spring 的事务管理器中配置全局的回滚规则。这通常通过在配置类中定义 TransactionManager 来实现。

  • 示例:自定义事务管理器
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

@Configuration
public class TransactionConfig {

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
        // 可以在这里配置全局的事务属性
        return transactionManager;
    }
}

4. 注意事项

异常捕获:
如果你在方法内部捕获了异常,并且没有重新抛出,事务管理器将无法感知异常,因此不会回滚事务。
示例:

@Transactional
public void myMethod() {
    try {
        // 业务逻辑
    } catch (Exception e) {
        // 捕获异常但没有重新抛出
    }
}

在这种情况下,事务不会回滚。
事务传播行为:
事务传播行为(如 Propagation.REQUIRES_NEW)也会影响事务回滚的行为。例如,如果一个方法的事务传播行为是 Propagation.REQUIRES_NEW,那么它会创建一个独立的事务,其回滚规则不会影响调用它的事务。
嵌套事务:
如果使用了嵌套事务(Propagation.NESTED),内层事务的回滚规则可能会影响外层事务的行为,具体取决于数据库的支持。
通过合理配置事务回滚规则,可以更好地控制事务的行为,确保在异常情况下数据的一致性。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。