Spring Boot 事务详解(事务传播行为、事务属性)

 更新时间:2025年05月20日 11:55:15   作者:Dong雨  
Spring Boot 提供了强大的事务管理功能,通过 @Transactional 注解可以方便地配置事务的传播行为和属性,本文将详细介绍 Spring Boot 中的事务管理,包括事务传播行为、事务属性以及声明式和编程式事务管理,感兴趣的朋友一起看看吧

Spring Boot 事务详解

引言

在现代应用程序中,事务管理是确保数据一致性和完整性的重要机制。Spring Boot 提供了强大的事务管理功能,使得开发者可以轻松地定义和管理事务。本文将详细介绍 Spring Boot 中的事务管理,包括事务传播行为、事务属性以及声明式和编程式事务管理。

声明式事务管理

声明式事务管理是通过注解的方式来管理事务,最常用的注解是 @Transactional。这种方式简单直观,适合大多数场景。

示例

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
    @Transactional
    public void createUser(User user) {
        // 数据库操作
    }
}

编程式事务管理

编程式事务管理是通过编程的方式来手动控制事务,通常使用 PlatformTransactionManagerTransactionTemplate

示例

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
@Service
public class UserService {
    @Autowired
    private PlatformTransactionManager transactionManager;
    public void createUser(User user) {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setName("createUserTransaction");
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus status = transactionManager.getTransaction(def);
        try {
            // 数据库操作
            transactionManager.commit(status);
        } catch (Exception e) {
            transactionManager.rollback(status);
            throw e;
        }
    }
}

事务传播行为

事务传播行为定义了当一个事务方法调用另一个事务方法时,事务如何传播。Spring 提供了多种传播行为,可以通过 @Transactional 注解进行配置。以下是 Spring 支持的传播行为及其使用场景:

1. REQUIRED

定义:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。

使用场景:大多数业务操作都使用该传播行为,因为它确保了调用链上的所有操作都在同一个事务中。

示例

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

事务传播示意图

+--------+              +--------+
|  方法A  |              |  方法B  |
|        |--------------->        |
|        | 传播事务 T1    |        |
+--------+              +--------+

2. SUPPORTS

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

使用场景:适用于可选的事务操作,例如只读查询。

示例

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

事务传播示意图

+--------+              +--------+
|  方法A  |              |  方法C  |
|        |--------------->        |
|        | 传播事务 T1    |        |
+--------+              +--------+

3. MANDATORY

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

使用场景:用于强制要求在事务环境中执行的方法。

示例

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

事务传播示意图

+--------+              +--------+
|  方法A  |              |  方法C  |
|        |--------------->        |
|        | 传播事务 T1    |        |
+--------+              +--------+

4. REQUIRES_NEW

定义:创建一个新的事务,如果当前存在事务,则将当前事务挂起。

使用场景:适用于必须在一个新事务中执行的操作,例如独立的日志记录。

示例

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

事务传播示意图

+--------+              +--------+
|  方法A  |              |  方法D  |
|        |------------->|        |
| 挂起事务 T1           | 创建事务 T2 |
+--------+              +--------+

5. NOT_SUPPORTED

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

使用场景:适用于不需要事务的操作,例如批量数据处理。

示例

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

事务传播示意图

+--------+              +--------+
|  方法A  |              |  方法E  |
|        |------------->|        |
| 挂起事务 T1           | 非事务执行 |
+--------+              +--------+

6. NEVER

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

使用场景:用于强制要求以非事务方式执行的方法。

示例

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

事务传播示意图

+--------+              +--------+
|  方法A  |              |  方法F  |
|        |------------->|        |
|        | 如果存在事务 T1,抛异常 |
+--------+              +--------+

7. NESTED

定义:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则行为与 REQUIRED 类似。

使用场景:适用于需要在主事务中执行的子事务,例如复杂的数据库操作。

示例

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

事务传播示意图

+--------+              +--------+
|  方法A  |              |  方法G  |
|        |------------->|        |
| 事务 T1             | 嵌套事务 T1.1 |
+--------+              +--------+

事务失效情况

Spring Boot 通过 Spring 框架的事务管理模块来支持事务操作。事务管理在 Spring Boot 中通常是通过 @Transactional 注解来实现的。以下是一些常见的事务失效情况:

1. 未捕获异常

如果一个事务方法中发生了未捕获的异常,并且异常未被处理或传播到事务边界之外,那么事务会失效,所有的数据库操作会回滚。

2. 非受检异常

默认情况下,Spring 对非受检异常(RuntimeException 或其子类)进行回滚处理,这意味着当事务方法中抛出这些异常时,事务会回滚。

3. 事务传播属性设置不当

如果在多个事务之间存在事务嵌套,且事务传播属性配置不正确,可能导致事务失效。特别是在方法内部调用有 @Transactional 注解的方法时要特别注意。

4. 多数据源的事务管理

如果在使用多数据源时,事务管理没有正确配置或者存在多个 @Transactional 注解时,可能会导致事务失效。

5. 跨方法调用事务问题

如果一个事务方法内部调用另一个方法,而这个被调用的方法没有 @Transactional 注解,这种情况下外层事务可能会失效。

6. 事务在非公开方法中失效

如果 @Transactional 注解标注在私有方法上或者非 public 方法上,事务也会失效。

7. 使用this调用事务方法

Spring 事务是通过代理对象来控制的,只有通过代理对象的方法调用才会应用事务管理的相关规则。当使用 this 直接调用时,是绕过了 Spring 的代理机制,因此不会应用事务设置。

回滚条件

1. 自动回滚事务

  • 抛出未检查异常(RuntimeException 及其子类),例如:NullPointerException 等。

2. 不会自动回滚

  • 默认情况下,检查异常(如 IOExceptionSQLException 等)不会触发回滚。可以通过 @Transactional 注解的 rollbackFor 属性配置回滚:

示例

@Transactional(rollbackFor = IOException.class)
public void methodH() {
    // 业务逻辑
}

事务属性

除了传播行为,Spring 还提供了一些其他事务属性,可以通过 @Transactional 注解进行配置。

1. 隔离级别

隔离级别定义了一个事务与其他事务隔离的程度。Spring 支持以下几种隔离级别:

  • DEFAULT:使用数据库默认的隔离级别。
  • READ_UNCOMMITTED:读未提交的变更。
  • READ_COMMITTED:读已提交的变更。
  • REPEATABLE_READ:可重复读。
  • SERIALIZABLE:串行化。

示例

@Transactional(isolation = Isolation.READ_COMMITTED)
public void methodI() {
    // 业务逻辑
}

2. 事务超时

事务超时定义了事务在回滚之前可以运行的最长时间(以秒为单位)。

示例

@Transactional(timeout = 30)
public void methodJ() {
    // 业务逻辑
}

3. 只读事务

只读事务用于优化只读操作。设置为只读的事务可以提示数据库引擎进行某些优化。

示例

@Transactional(readOnly = true)
public void methodK() {
    // 业务逻辑
}

4. 回滚规则

通过 rollbackFornoRollbackFor 属性可以指定哪些异常会触发事务回滚,哪些不会。

示例

@Transactional(rollbackFor = Exception.class)
public void methodL() {
    // 业务逻辑
}

常见面试题解析

1. 什么是事务传播行为?Spring 提供了哪些事务传播行为?

:事务传播行为定义了当一个事务方法调用另一个事务方法时,事务如何传播。Spring 提供了以下事务传播行为:REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED。

2. 如何配置事务的隔离级别?Spring 提供了哪些隔离级别?

:可以通过 @Transactional 注解的 isolation 属性配置事务的隔离级别。Spring 提供了以下隔离级别:DEFAULT、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE。

3. 什么是只读事务?如何配置?

:只读事务用于优化只读操作。可以通过 @Transactional 注解的 readOnly 属性配置只读事务。例如:@Transactional(readOnly = true)

4. 如何配置事务的超时时间?

:可以通过 @Transactional 注解的 timeout 属性配置事务的超时时间(以秒为单位)。例如:@Transactional(timeout = 30)

5. 如何指定哪些异常会触发事务回滚?

:可以通过 @Transactional 注解的 rollbackFor 属性指定哪些异常会触发事务回滚。例如:@Transactional(rollbackFor = Exception.class)

总结

Spring Boot 提供了强大的事务管理功能,通过 @Transactional 注解可以方便地配置事务的传播行为和属性。理解和合理应用这些配置,可以有效地提高应用程序的数据一致性和完整性。

到此这篇关于Spring Boot 事务详解(事务传播行为、事务属性)的文章就介绍到这了,更多相关Spring Boot 事务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • springboot实现微信扫码登录的项目实践

    springboot实现微信扫码登录的项目实践

    微信扫码功能是目前第三方登录常见功能,前不久有个项目刚好用上,本文主要介绍了springboot实现微信扫码登录的项目实践,具有一定的参考价值,感兴趣的可以了解一下
    2023-10-10
  • Mybatis 条件查询 批量增删改查功能

    Mybatis 条件查询 批量增删改查功能

    这篇文章主要介绍了mybatis 脚本处理语句之条件查询 批量增删改查功能,需要的的朋友参考下吧
    2017-06-06
  • 使用Spring的ApplicationEvent实现本地事件驱动的实现方法

    使用Spring的ApplicationEvent实现本地事件驱动的实现方法

    本文介绍了如何使用Spring的ApplicationEvent实现本地事件驱动,通过自定义事件和监听器,实现模块之间的松耦合,提升代码的可维护性和扩展性。同时还介绍了异步事件和事件传递的相关知识
    2023-04-04
  • maven工程中读取resources中的资源文件

    maven工程中读取resources中的资源文件

    Web项目中应该经常有这样的需求,在maven项目的resources目录下放一些文件,比如一些配置文件,资源文件等,本文主要介绍了maven工程中读取resources中的资源文件,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • java 输入3个数a,b,c,按大小顺序输出的实例讲解

    java 输入3个数a,b,c,按大小顺序输出的实例讲解

    今天小编就为大家分享一篇java 输入3个数a,b,c,按大小顺序输出的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • 详解Java 自动装箱与自动拆箱

    详解Java 自动装箱与自动拆箱

    这篇文章主要介绍了Java 自动装箱与自动拆箱的相关资料,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下
    2020-09-09
  • Java中的CountDownLatch同步工具类使用解析

    Java中的CountDownLatch同步工具类使用解析

    这篇文章主要介绍了Java中的CountDownLatch使用解析,CountDownLatch初始化的时候必须指定一个count,await方法会一直阻塞直到调用countdown方法,count为0,当count为0时,所有的等待线程都会被释放,需要的朋友可以参考下
    2023-12-12
  • 使用JAVA实现高并发无锁数据库操作步骤分享

    使用JAVA实现高并发无锁数据库操作步骤分享

    一个在线2k的游戏,每秒钟并发都吓死人。传统的hibernate直接插库基本上是不可行的。我就一步步推导出一个无锁的数据库操作,详情看下文
    2013-11-11
  • Spring源码解析 Bean属性填充

    Spring源码解析 Bean属性填充

    这篇文章主要介绍了Spring源码解析 Bean属性填充,文章围绕主题展开想详细的内容详情,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-07-07
  • Java编程中的4种代码块详解

    Java编程中的4种代码块详解

    在本篇内容里小编个总结了Java编程中的4种代码块相关的知识点,有兴趣的朋友们可以学习下。
    2021-06-06

最新评论