当前位置: 首页 > article >正文

【Spring】深入理解 Spring 事务管理

文章目录

  • 一、事务的基本概念​
      • 原子性(Atomicity)
      • 一致性(Consistency)
      • 隔离性(Isolation)
      • 持久性(Durability)
  • 二、Spring 事务管理的优势​
      • 简化事务管理代码
      • 提供多种事务管理方式
      • 整合多种持久化技术
  • 三、Spring 事务管理的核心接口​
      • PlatformTransactionManager
      • TransactionDefinition
      • TransactionStatus
  • 四、事务传播行为​
  • 五、事务隔离级别​
  • 六、声明式事务管理​
  • 七、事务的回滚规则​
  • 八、事务失效场景​

在当今的企业级应用开发中,数据的一致性和完整性是至关重要的。而 Spring 框架提供的事务管理功能,为我们解决这一关键问题提供了强大的支持。本文将深入探讨 Spring 事务管理的相关知识,帮助大家更好地理解和运用它。​

一、事务的基本概念​

事务是一组逻辑操作单元,这些操作要么全部成功,要么全部失败。例如在银行转账场景中,从账户 A 向账户 B 转账 100 元,涉及到从账户 A 扣款 100 元和向账户 B 存款 100 元两个操作,这两个操作必须作为一个整体来执行,要么都成功,否则就会导致数据不一致。事务具有 ACID 特性:​

原子性(Atomicity)

事务中的所有操作要么全部执行成功,要么全部失败回滚,就像一个原子一样不可分割。​

一致性(Consistency)

事务执行前后,数据库的完整性约束没有被破坏,数据从一个一致性状态转换到另一个一致性状态。​

隔离性(Isolation)

多个事务并发执行时,一个事务的执行不能被其他事务干扰,各个事务之间相互隔离。​

持久性(Durability)

一旦事务提交成功,对数据库所做的修改就会永久保存下来,即使系统发生故障也不会丢失。​

二、Spring 事务管理的优势​

简化事务管理代码

传统的 JDBC 事务管理需要编写大量的样板代码来处理事务的开始、提交、回滚等操作,而 Spring 通过声明式事务管理,让我们可以通过简单的配置或注解来管理事务,大大减少了代码量。​

提供多种事务管理方式

Spring 支持编程式事务管理和声明式事务管理。编程式事务管理通过编写代码来控制事务,灵活性较高;声明式事务管理则通过配置或注解来指定事务的边界和属性,更符合面向切面编程(AOP)的思想,便于维护和管理。​

整合多种持久化技术

Spring 事务管理可以与多种持久化技术如 JDBC、Hibernate、JPA 等无缝集成,无论你使用哪种持久化技术,都能方便地进行事务管理。​

三、Spring 事务管理的核心接口​

PlatformTransactionManager

这是 Spring 事务管理的核心接口,它提供了事务管理的基本方法,如获取事务、提交事务、回滚事务等。不同的持久化技术对应不同的实现类,例如对于 JDBC,有 DataSourceTransactionManager;对于 Hibernate,有 HibernateTransactionManager 等。​

TransactionDefinition

该接口定义了事务的属性,包括事务的传播行为、隔离级别、超时时间、是否只读等。通过设置这些属性,可以灵活地控制事务的行为。​

TransactionStatus

代表一个事务的状态,通过它可以获取事务的相关信息,如是否新事务、是否已完成等,还可以手动回滚事务。​

四、事务传播行为​

事务传播行为定义了一个事务方法被另一个事务方法调用时,事务应该如何传播。Spring 定义了 7 种事务传播行为:​
PROPAGATION_REQUIRED(默认):如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新事务。例如方法 A 调用方法 B,若方法 A 已经在一个事务中,方法 B 会加入方法 A 的事务;若方法 A 没有事务,方法 B 会创建一个新事务。​
PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。​
PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。​
PROPAGATION_REQUIRES_NEW:总是创建一个新事务。如果当前存在事务,则将当前事务挂起,直到新事务执行完毕。​
PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作。如果当前存在事务,则将当前事务挂起。​
PROPAGATION_NEVER:以非事务方式执行操作。如果当前存在事务,则抛出异常。​
PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则创建一个新事务。嵌套事务可以独立于外部事务进行回滚或提交,但外部事务回滚时,嵌套事务也会回滚。​

五、事务隔离级别​

事务隔离级别用于解决多个事务并发执行时可能出现的问题,如脏读、不可重复读、幻读等。Spring 支持以下 5 种事务隔离级别:​
ISOLATION_DEFAULT:使用底层数据库默认的隔离级别。​
ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、不可重复读和幻读。​
ISOLATION_READ_COMMITTED:允许读取并发事务已经提交的数据,避免了脏读,但可能会出现不可重复读和幻读。​
ISOLATION_REPEATABLE_READ:对同一字段的多次读取结果是一致的,除非数据被当前事务本身修改,避免了脏读和不可重复读,但可能会出现幻读。​
ISOLATION_SERIALIZABLE:最高的隔离级别,完全串行化的事务,避免了脏读、不可重复读和幻读,但性能开销较大。​

六、声明式事务管理​

声明式事务管理是 Spring 推荐的事务管理方式,它基于 AOP 实现。在 Spring 中,可以通过 XML 配置或注解来实现声明式事务管理。

@Servicepublic class OrderService {@Autowiredprivate OrderDao orderDao;​
​
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)public void placeOrder(Order order) {​
        orderDao.save(order);}}

在@Transactional注解中可以指定事务的传播行为、隔离级别等属性。

七、事务的回滚规则​

默认情况下,Spring 事务在遇到运行时异常(RuntimeException 及其子类)和错误(Error)时会自动回滚事务,而遇到受检异常(Checked Exception)时不会自动回滚事务。但我们可以通过@Transactional注解的rollbackFor和noRollbackFor属性来指定回滚规则。​
1. rollbackFor:指定需要回滚事务的异常类型,例如:

@Transactional(rollbackFor = CustomBusinessException.class)public void businessMethod() {// 业务逻辑​
}

这里指定了遇到CustomBusinessException异常时回滚事务。​
2. noRollbackFor:指定不需要回滚事务的异常类型,例如:

@Transactional(noRollbackFor = DataAccessException.class)public void dataAccessMethod() {// 数据访问逻辑​
}

这里表示遇到DataAccessException异常时不回滚事务。

八、事务失效场景​

1. 方法内部调用:当一个类中的非事务方法调用同一类中的事务方法时,事务会失效。因为 Spring 的声明式事务是基于 AOP 代理实现的,在类内部方法调用时,并不会经过代理对象,事务增强逻辑也就不会生效。例如:

@Servicepublic class UserService {@Autowiredprivate UserDao userDao;​
​
    public void nonTransactionalMethod() {// 内部调用事务方法​
        transactionalMethod();}​
​
    @Transactionalpublic void transactionalMethod() {​
        userDao.save(new User());}}

在上述代码中,nonTransactionalMethod内部调用transactionalMethod,此时transactionalMethod上的事务不会生效。解决办法是将调用逻辑抽取到另一个被 Spring 管理的服务类中,通过依赖注入进行调用。​
2. 未被 Spring 管理的类:如果一个类没有被 Spring 容器管理,那么它上面的@Transactional注解不会生效。比如,在一个普通的 Java 类中使用@Transactional,事务不会起作用。确保所有需要事务管理的类都通过@Component、@Service、@Repository等注解交由 Spring 管理。​
3. 不支持事务的数据源:若使用的数据源本身不支持事务,如某些轻量级的嵌入式数据库默认不开启事务支持,那么即使配置了 Spring 事务管理,事务也无法正常工作。需要检查并确保所使用的数据源具备事务处理能力,并且正确配置了事务相关参数。​
4. 异常被捕获处理:当事务方法内部捕获了异常,却没有重新抛出运行时异常或错误,事务不会回滚。例如:

@Transactionalpublic void saveUser(User user) {try {​
        userDao.save(user);int i = 1 / 0; // 模拟异常​
    } catch (Exception e) {// 捕获异常但未抛出运行时异常​
        log.error("操作出错", e);}}

在这种情况下,事务不会回滚。正确做法是在捕获异常后,根据业务逻辑决定是否重新抛出运行时异常,如throw new RuntimeException(e)。​
5. 错误的事务传播机制设置:在使用事务传播行为时,如果设置不当,也可能导致事务失效。例如,将一个方法的事务传播行为设置为PROPAGATION_NOT_SUPPORTED,那么该方法内的事务操作实际上是在无事务环境下执行的。需要根据业务场景合理选择事务传播行为。​
6. 多线程调用:在多线程环境下,Spring 的事务管理基于线程绑定来工作。如果在一个线程中开启事务,然后在另一个线程中执行事务相关操作,事务上下文无法传递,导致事务失效。要避免在多线程场景下直接使用 Spring 事务管理,可考虑使用支持分布式事务的解决方案,如 Seata 等。


http://www.kler.cn/a/597801.html

相关文章:

  • Cesium 自定义路径导航材质
  • 运算放大器(一)运算放大器的参数、选型与应用
  • 防火墙设置屏蔽漏洞
  • 【leetcode题解】链表
  • mysql5.7及mysql8的一些特性
  • python包和模块
  • 深入理解指针(1)(C语言版)
  • 计算机操作系统(六) 进程控制与进程通信 (附带图谱更好对比理解)
  • 指针,数组 易混题解析(一)
  • 在 .NET 9.0 Web API 中实现 Scalar 接口文档及JWT集成
  • JavaEE-MyBatis概述第一个程序
  • 生活电子常识-deepseek-r1本地化部署+ui界面搭建
  • 练习:自动驾驶
  • xy轴不等比缩放问题——AUTOCAD c#二次开发
  • 【leetcode题解】宽搜(BFS)
  • AI 驱动视频处理与智算革新:蓝耘MaaS释放海螺AI视频生产力
  • HTTP/HTTPS 中 GET 请求和 POST 请求的区别与联系
  • Python基于深度学习的中文情感分析系统(V2.0,附源码,文档说明)
  • 汽车制造MES
  • langfuse追踪Trace