程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 若依框架
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 若依框架
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • 快速入门

  • 后端手册

    • 分页实现
    • 导入导出功能
    • 文件上传与下载
    • 权限注解实现
    • 事务管理详解
      • 一、Spring Boot 项目中的事务管理
      • 二、@Transactional 注解的基本使用
      • 三、事务回滚机制
      • 四、常见事务管理坑点
        • 1. 检查异常不回滚
        • 2. 业务层捕获异常导致事务失效
      • 五、@Transactional 注解的常用属性
      • 六、事务传播机制
      • 七、总结与最佳实践
    • 全局异常处理
    • 参数验证详解
    • 数据脱敏详解
    • 系统日志功能实现
    • 数据权限控制
    • 多数据源实现
    • 代码生成功能
    • 定时任务实现
    • 系统接口文档生成
    • 防重复提交实现
    • 国际化支持
    • 新建子模块
  • 前端手册

  • 组件文档

  • 数据库分析

  • 若依框架
  • 后端手册
scholar
2024-08-31
目录

事务管理详解

# 事务管理

在企业级应用中,事务管理是保障数据一致性的重要手段。Spring Framework 提供了强大的事务管理功能,而若依框架则通过整合 Spring Boot 简化了事务管理的配置和使用。本文将详细介绍如何在若依框架中实现和使用事务管理,并涵盖常见的使用场景、注意事项以及可能遇到的坑点。

# 一、Spring Boot 项目中的事务管理

在一个标准的 Spring Boot 项目中,通常会引入 spring-boot-starter 或 spring-boot-starter-web 依赖。这些依赖包已经默认包含了对 spring-boot-starter-jdbc 或 spring-boot-starter-data-jpa 的依赖。因此,框架会自动为你配置 DataSourceTransactionManager(用于 JDBC)或 JpaTransactionManager(用于 JPA)作为事务管理器。

这意味着你可以直接在方法或类上使用 @Transactional 注解来管理事务,而无需额外的配置。

# 二、@Transactional 注解的基本使用

@Transactional 注解用于声明方法或类中的事务行为。该注解通常应用于 public 可见度的方法上,可以应用于接口定义和接口方法。方法上的 @Transactional 注解会覆盖类级别的事务声明。

示例: 用户新增时,插入用户表、用户与岗位关联表、用户与角色关联表的数据。为了确保数据的一致性,可以使用事务管理来实现,如果中间任何一步失败,则回滚所有操作。

@Transactional
public int insertUser(User user) {
    // 新增用户信息
    int rows = userMapper.insertUser(user);
    // 新增用户岗位关联
    insertUserPost(user);
    // 新增用户与角色关联
    insertUserRole(user);
    return rows;
}
1
2
3
4
5
6
7
8
9
10

在上面的例子中,如果 insertUserPost 或 insertUserRole 方法抛出异常,整个事务将被回滚,已插入的用户信息也会被撤销。

# 三、事务回滚机制

Spring 的默认事务回滚规则是:仅在遇到 RuntimeException 或 Error 时才回滚事务。如果希望在遇到其他类型的异常时也回滚事务,可以通过 rollbackFor 属性指定异常类型。

示例: 在遇到 SQLException 时回滚事务。

@Transactional(rollbackFor = Exception.class)
public int insertUser(User user) throws Exception {
    // 新增用户信息
    int rows = userMapper.insertUser(user);
    // 新增用户岗位关联
    insertUserPost(user);
    // 新增用户与角色关联
    insertUserRole(user);
    
    // 模拟抛出 SQLException 异常
    boolean flag = true;
    if (flag) {
        throw new SQLException("发生异常了..");
    }
    return rows;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

在上述代码中,rollbackFor = Exception.class 确保了即使遇到 SQLException 这样的检查异常,事务也会回滚。

# 四、常见事务管理坑点

# 1. 检查异常不回滚

默认情况下,Spring 只在 RuntimeException 或 Error 时回滚事务。如果你的代码中抛出的是检查异常(如 SQLException),事务将不会回滚。要确保事务在检查异常发生时也回滚,可以使用 rollbackFor 属性。

# 2. 业务层捕获异常导致事务失效

在业务层捕获异常并处理后,事务不会回滚,因为 Spring 无法感知到异常的发生。

错误示例:

@Transactional
public int insertUser(User user) throws Exception {
    // 新增用户信息
    int rows = userMapper.insertUser(user);
    // 新增用户岗位关联
    insertUserPost(user);
    // 新增用户与角色关联
    insertUserRole(user);

    try {
        // 模拟抛出 SQLException 异常
        throw new SQLException("发生异常了..");
    } catch (Exception e) {
        e.printStackTrace();  // 异常被捕获并处理,事务不会回滚
    }
    
    return rows;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

推荐做法: 在业务层统一抛出异常,让控制层来处理异常,从而确保事务回滚。

@Transactional
public int insertUser(User user) throws Exception {
    // 新增用户信息
    int rows = userMapper.insertUser(user);
    // 新增用户岗位关联
    insertUserPost(user);
    // 新增用户与角色关联
    insertUserRole(user);

    // 模拟抛出 RuntimeException 异常
    boolean flag = true;
    if (flag) {
        throw new RuntimeException("发生异常了..");
    }
    
    return rows;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 五、@Transactional 注解的常用属性

属性 说明
propagation 事务的传播行为,默认值为 REQUIRED。
isolation 事务的隔离级别,默认值为 DEFAULT。
timeout 事务的超时时间,默认值为 -1,表示不超时。如果超过该时间限制但事务还未完成,则回滚事务。
read-only 指定事务是否为只读事务,默认值为 false。对于只读取数据的方法,可以将其设置为 true。
rollbackFor 用于指定触发事务回滚的异常类型,可以指定多个异常类型,之间用逗号分隔。
noRollbackFor 指定不触发事务回滚的异常类型,多个异常类型之间用逗号分隔。

# 六、事务传播机制

事务传播机制指定了当一个事务性方法调用另一个事务性方法时,如何处理事务。常用的传播行为如下:

常量 含义
TransactionDefinition.PROPAGATION_REQUIRED 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
TransactionDefinition.PROPAGATION_REQUIRES_NEW 创建一个新的事务,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_SUPPORTS 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER 以非事务方式运行,如果当前存在事务,则抛出异常。
TransactionDefinition.PROPAGATION_MANDATORY 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
TransactionDefinition.PROPAGATION_NESTED 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则等同于 REQUIRED。

通过合理使用 @Transactional 注解和事务传播机制,可以确保在不同场景下的数据一致性和业务逻辑的完整性。

# 七、总结与最佳实践

  • 事务控制边界: 建议在服务层(Service Layer)进行事务控制,而不是在 DAO 层或控制层。
  • 异常处理: 在业务层中尽量不要捕获并处理异常,而是让异常冒泡到控制层进行统一处理,以确保事务能正确回滚。
  • 传播机制选择: 根据业务需求选择合适的事务传播机制,例如在某些情况下使用 REQUIRES_NEW 来确保子事务的独立性。
  • 性能优化: 对于只读的操作,可以通过设置 read-only = true 来优化性能。
编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08
权限注解实现
全局异常处理

← 权限注解实现 全局异常处理→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式