深入了解Spring事务及其使用场景

embedded/2025/3/29 6:18:08/

介绍

在企业级应用开发中,数据的一致性和完整性至关重要。Spring 事务管理作为 Spring 框架的核心功能之一,为开发者提供了一种便捷且强大的方式来确保数据库操作在逻辑上的原子性。无论是简单的单数据库事务,还是涉及多个数据源的分布式事务,Spring 都提供了相应的解决方案。本文将深入探讨 Spring 事务的原理、应用场景,并通过实际例子展示其具体用法。这里暂时只讨论单数据库的情况,多个数据库需要使用Spring Cloud分布式事务组件像Seata,这里就不过多赘述。

Spring 事务管理

Spring 提供了一个统一的事务管理抽象层,允许开发者使用不同的事务管理策略,而无需关心底层事务实现的细节。主要涉及以下几个关键接口和类:

  • PlatformTransactionManager:事务管理器接口,不同的持久化技术(如 JDBC、Hibernate 等)都有对应的实现类。它负责管理事务的创建、提交和回滚。
  • TransactionDefinition:定义事务的属性,如事务隔离级别、传播行为、超时时间等。
  • TransactionStatus:代表一个事务的运行状态,事务管理器可以通过它来控制事务的执行过程。

事务隔离级别

事务隔离级别定义了一个事务与其他并发事务之间的隔离程度,以防止并发访问导致的数据不一致问题。Spring 支持以下几种事务隔离级别(也是MySQL数据库的事务隔离级别,MySQL 的默认事务隔离级别是 REPEATABLE READ。):

  • DEFAULT:使用底层数据库默认的隔离级别。
  • READ_UNCOMMITTED:最低的隔离级别,一个事务可以读取另一个未提交事务的数据,可能导致脏读、不可重复读和幻读。
  • READ_COMMITTED:一个事务只能读取已提交事务的数据,可避免脏读,但仍可能出现不可重复读和幻读。
  • REPEATABLE_READ(MySQL默认的隔离级别:保证在同一事务中多次读取同一数据时,数据保持一致,可避免脏读和不可重复读,但可能出现幻读。
  • SERIALIZABLE:最高的隔离级别,通过强制事务串行执行,避免了所有并发问题,但性能开销较大。

事务传播行为

事务传播行为定义了当一个事务方法被另一个事务方法调用时,应该如何管理事务。Spring 定义了七种事务传播行为:

  • PROPAGATION_REQUIRED(默认):如果当前存在事务,则加入该事务;如果不存在事务,则创建一个新的事务。这是默认的传播行为。
  • PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果不存在事务,则以非事务方式执行。
  • PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果不存在事务,则抛出异常。
  • PROPAGATION_REQUIRES_NEW:总是创建一个新的事务,如果当前存在事务,则挂起当前事务。
  • PROPAGATION_NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,则挂起当前事务。
  • PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
  • PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行;如果不存在事务,则创建一个新的事务。嵌套事务可以独立于外层事务进行回滚或提交。

这七种事务传播行为可以记为required/requires_new,supports/not_supported,mandatory/nevernested。

事务应用场景

数据一致性保障

在涉及单个数据库多表,或者多个数据库操作的业务场景中,如订单创建时同时更新库存和用户账户余额,需要确保这些操作要么全部成功,要么全部失败,以维持数据的一致性。

业务流程完整性

例如在电商系统中,完成一次订单支付操作可能涉及多个步骤,包括扣除用户账户金额、更新订单状态、记录支付日志等。这些操作必须作为一个整体来执行,以保证业务流程的完整性。

错误处理与回滚

当业务操作过程中出现异常时,通过事务的自动回滚机制,可以确保数据不会处于不一致的状态。比如在文件上传并同时更新数据库记录的场景中,如果文件上传失败,数据库的相关记录更新也应该回滚。

Spring事务的两种实现方式

Spring 事务的实现方式主要有两种:编程式事务和声明式事务。

编程式事务

编程式事务管理允许开发者在代码中通过编程的方式精确控制事务的边界。它提供了最大的灵活性,适用于一些复杂的事务控制场景,但代码侵入性较高。

使用 TransactionTemplateTransactionTemplate 是 Spring 提供的用于编程式事务管理的核心类。通过它,开发者可以在代码块中定义事务的执行逻辑。TransactionTemplate 的 execute 方法接收一个 TransactionCallback 对象。在 doInTransaction 方法中编写具体的数据库操作逻辑。如果在执行过程中抛出异常,通过 status.setRollbackOnly() 方法回滚事务。

声明式事务

声明式事务管理是基于 AOP(面向切面编程)的思想,通过在方法或类上添加注解的方式来声明事务的边界和属性。这种方式对业务代码的侵入性较低,使得事务管理与业务逻辑分离,提高了代码的可维护性和可读性。Spring 支持两种声明式事务管理的方式:

  • 基于 XML 配置:在 Spring 的配置文件中,通过 <tx:advice> 和 <aop:config> 标签来配置事务。
<!-- 配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!-- 定义事务通知 --><tx:advice id="txAdvice" transaction - manager="transactionManager"><tx:attributes><tx:method name="save*" propagation="REQUIRED"/><tx:method name="update*" propagation="REQUIRED"/><tx:method name="delete*" propagation="REQUIRED"/><tx:method name="*" read - only="true"/></tx:attributes></tx:advice><!-- 配置AOP,将事务通知应用到指定的切入点 --><aop:config><aop:pointcut id="serviceMethods" expression="execution(* com.example.demo.service.*.*(..))"/><aop:advisor advice - ref="txAdvice" pointcut - ref="serviceMethods"/></aop:config>

 首先定义了 TransactionManager,然后通过 <tx:advice> 定义了事务的属性(如哪些方法需要事务以及事务的传播行为),最后通过 <aop:config> 将事务通知应用到指定的切入点(这里是 com.example.demo.service 包下的所有方法)。

  • 基于注解:使用@Transactional注解来标记需要事务管理的方法或类。当注解在类上时,该类的所有公共方法都将应用事务管理。
java">@Service
public class ProductService {@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)public void saveProduct(Product product) {// 保存产品的数据库操作}@Transactional(readOnly = true)public Product getProductById(int id) {// 获取产品的数据库操作return null;}
}

 在上述代码中,saveProduct 方法上的 @Transactional 注解指定了事务的传播行为为 REQUIRED,并且当方法抛出任何异常时都回滚事务。getProductById 方法上的 @Transactional 注解设置了事务为只读。

这两种实现方式各有优劣,编程式事务管理适合复杂的事务控制场景,而声明式事务管理更适合大多数常规的事务管理需求,能有效减少代码冗余,提高开发效率。开发者可以根据具体的业务场景选择合适的事务管理方式。

总结

Spring 事务管理为开发者提供了一种高效、灵活的方式来处理数据库事务,确保数据的一致性和业务流程的完整性。通过深入理解事务的基本概念、隔离级别、传播行为以及实际应用场景,并结合具体的代码示例,开发者能够在实际项目中合理运用 Spring 事务,构建出稳定、可靠的企业级应用。随着业务复杂度的增加,合理选择事务策略和处理分布式事务将成为关键,这也是 Spring 事务管理持续发展和优化的方向。


http://www.ppmy.cn/embedded/176016.html

相关文章

MAC-在使用@Async注解的方法时,分布式锁管理和释放

在使用 @Async 注解的异步方法中管理分布式锁时,需要特别注意 ​锁的获取、释放与异步执行的生命周期匹配。以下是结合 Spring Boot 和 Redis 分布式锁的实践方案: 1. 为什么需要分布式锁? 异步方法可能被多个线程/服务实例并发执行,若访问共享资源(如数据库、缓存),需…

玩客云 armbian 安装mqtt服务端

1. 准备工作 确保玩客云已刷入Armbian系统&#xff0c;并能通过SSH正常连接。 更新系统软件包&#xff1a; sudo apt update && sudo apt upgrade -y 2. 安装Mosquitto MQTT服务端 sudo apt install mosquitto mosquitto-clients -y 3. 配置Mosquitto 修改配置文件&…

Springboot实现使用断点续传优化同步导入Excel

springboot实现使用断点续传优化同步导入Excel 需求前言断点续传前端实现后端实现完结撒花&#xff0c;如有需要收藏的看官&#xff0c;顺便也用发财的小手点点赞哈&#xff0c;如有错漏&#xff0c;也欢迎各位在评论区评论&#xff01; 需求前言 在跨境电商系统中&#xff0c…

c++进阶之------红黑树

一、概念 红黑树&#xff08;Red-Black Tree&#xff09;是一种自平衡二叉查找树&#xff0c;它在计算机科学的许多领域中都有广泛应用&#xff0c;比如Java中的TreeMap和C中的set/map等数据结构的底层实现。红黑树通过在每个节点上增加一个颜色属性&#xff08;红色或黑色&am…

数据库三级选择题(1)

7D人机界面的设计可采用原型迭代法&#xff0c;首先进行初步设计&#xff0c;再进行用户界面细节设计&#xff0c;最后是原型设计与改进。 11&#xff1f;在一台正在运行的SQL Server 2008中&#xff0c;现需使用复制数据库文件的方法将某数据库从一台服务器移动到另一台服务器…

基于python+django的酒店预定网站-酒店管理系统源码+运行步骤+课程学习

该系统是基于pythondjango开发的酒店预定管理系统。适用场景&#xff1a;大学生、课程作业、毕业设计。学习过程中&#xff0c;如遇问题可在github给作者留言。共同学习技术 演示地址 前台地址&#xff1a; http://hotel.gitapp.cn 后台地址&#xff1a; http://hotel.gitapp…

能源监控软件UI界面设计:平衡功能性与审美性的艺术

在当今社会&#xff0c;能源作为推动经济发展的重要基石&#xff0c;其高效管理和合理利用显得尤为重要。随着科技的进步&#xff0c;能源监控软件应运而生&#xff0c;成为连接能源使用者与管理者之间的桥梁。而软件的UI&#xff08;用户界面&#xff09;设计&#xff0c;作为…

《基于Spring Boot+Vue的智慧养老系统的设计与实现》开题报告

个人主页:@大数据蟒行探索者 一、研究背景及国内外研究现状 1.研究背景 根据1982年老龄问题世界大会联合国制定的标准,如果一个国家中超过65岁的老人占全国总人口的7%以上,或者超过60岁的老人占全国总人口的10%以上,那么这个国家将被定义为“老龄化社会”[1]。 随着国…