Spring 事务及管理方式

devtools/2025/2/19 7:56:49/

Spring 事务管理是 Spring 框架的核心功能之一,它为开发者提供了一种方便、灵活且强大的方式来管理数据库事务。

1、事务的基本概念

事务是一组不可分割的操作序列,这些操作要么全部成功执行,要么全部失败回滚,以确保数据的一致性和完整性。事务具有四个特性,即 ACID 特性:

  • 原子性(Atomicity):事务中的所有操作要么全部执行成功,要么全部失败回滚。

  • 一致性(Consistency):事务执行前后,数据库的状态必须保持一致。

  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不能被其他事务干扰。

  • 持久性(Durability):事务一旦提交,其对数据库的更改将永久保存。

2、事务的传播行为

事务的传播行为定义了在嵌套事务场景下,事务如何传播。Spring 定义了 7 种事务传播行为:

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

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

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

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

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

  • PROPAGATION_NEVER:以非事务方式执行操作,如果当前存在事务,则抛出异常。

  • PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则创建一个新的事务。

使用 @Transactional 注解指定传播行为的示例:

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {@Transactional(propagation = Propagation.REQUIRES_NEW)public void transferMoney() {// 执行数据库操作}
}

3、事务的隔离级别

事务的隔离级别定义了一个事务对其他事务的可见性。Spring 支持 4 种事务隔离级别:

  • ISOLATION_DEFAULT:使用数据库默认的隔离级别。

  • ISOLATION_READ_UNCOMMITTED:允许读取未提交的数据,可能会导致脏读、不可重复读和幻读。

  • ISOLATION_READ_COMMITTED:只允许读取已提交的数据,可以避免脏读,但可能会导致不可重复读和幻读。

  • ISOLATION_REPEATABLE_READ:确保在同一个事务中多次读取同一数据的结果是一致的,可以避免脏读和不可重复读,但可能会导致幻读。

  • ISOLATION_SERIALIZABLE:最高的隔离级别,确保事务串行执行,可以避免脏读、不可重复读和幻读,但会影响并发性能。

使用 @Transactional 注解指定隔离级别的示例:

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {@Transactional(isolation = Isolation.READ_COMMITTED)public void transferMoney() {// 执行数据库操作}
}

4、Spring 事务管理的实现方式

Spring 提供了两种事务管理方式:编程式事务管理和声明式事务管理。

4.1 编程式事务管理

编程式事务管理需要在代码中显式地管理事务的开始、提交和回滚。Spring 提供了 TransactionTemplatePlatformTransactionManager 来实现编程式事务管理。

使用 TransactionTemplate 的示例:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;@Service
public class UserService {@Autowiredprivate TransactionTemplate transactionTemplate;public void transferMoney() {transactionTemplate.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus status) {try {// 执行数据库操作// 例如:从账户 A 转账到账户 B} catch (Exception e) {status.setRollbackOnly();}}});}
}

使用 PlatformTransactionManager的示例:

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 {@Autowiredprivate PlatformTransactionManager transactionManager;public void addUser() {TransactionDefinition def = new DefaultTransactionDefinition();TransactionStatus status = transactionManager.getTransaction(def);try {// 业务逻辑代码transactionManager.commit(status);} catch (Exception e) {transactionManager.rollback(status);}}
}

解释 

  • PlatformTransactionManager:Spring 提供的事务管理器接口,用于管理事务的提交、回滚等操作。

  • TransactionDefinition:定义事务的属性,如隔离级别、传播行为等。

  • TransactionStatus:表示当前事务的状态,通过 transactionManager.getTransaction(def) 方法获取。

  • 手动提交和回滚:在代码中手动调用 transactionManager.commit(status) 提交事务,调用 transactionManager.rollback(status) 回滚事务。

优缺点

  • 优点

    • 对事务的控制非常精细,可以根据业务逻辑在代码的任何位置灵活地开启、提交或回滚事务。

    • 适用于复杂的事务处理场景,例如需要根据不同的业务条件动态决定是否提交或回滚事务。

  • 缺点

    • 代码中会包含大量的事务管理代码,导致业务逻辑和事务管理逻辑耦合度高,增加了代码的复杂度和维护难度。

    • 当业务逻辑发生变化时,可能需要同时修改事务管理代码,不符合开闭原则。

适用场景

  • 事务逻辑复杂,需要根据业务条件动态控制事务的提交和回滚。

  • 对事务管理有特殊需求,例如需要在事务中执行一些非数据库操作,并且要保证这些操作与数据库操作的原子性。

4.2 声明式事务管理

声明式事务管理是通过 AOP(面向切面编程)实现的,它允许开发者通过配置的方式来定义事务的边界,而不需要在代码中显式地管理事务。声明式事务管理有两种配置方式:基于 XML 配置和基于注解配置。

@Transactional 注解默认的事务隔离级别是 ISOLATION_DEFAULT

@Transactional 注解默认的事务传播行为是 PROPAGATION_REQUIRED

基于注解配置的示例:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {@Autowiredprivate UserDao userDao;@Transactionalpublic void transferMoney() {// 执行数据库操作// 例如:从账户 A 转账到账户 B}
}

解释

  • @Transactional 注解:在方法上添加 @Transactional 注解,Spring 会自动管理该方法的事务。如果方法执行过程中抛出异常,Spring 会自动回滚事务。

在配置类中开启事务注解支持:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.sql.DataSource;@Configuration
@EnableTransactionManagement
public class AppConfig {@Autowiredprivate DataSource dataSource;@Beanpublic PlatformTransactionManager transactionManager() {return new DataSourceTransactionManager(dataSource);}
}

优缺点

  • 优点

    • 事务管理代码与业务逻辑分离,降低了代码的耦合度,使业务代码更加简洁、清晰,易于维护。

    • 通过配置的方式定义事务,提高了开发效率,减少了重复代码。

  • 缺点

    • 事务的控制粒度相对较粗,不够灵活。例如,无法在方法内部的某个具体位置精确控制事务的提交和回滚。

    • 由于是基于 AOP 实现的,可能会带来一定的性能开销。

适用场景

  • 事务逻辑相对简单,且事务边界比较固定的场景。

  • 大多数业务方法都需要相同的事务管理策略,通过统一的注解配置可以提高开发效率。

注意事项:

1. 注意 @Transactional 注解位置

该注解可以用在方法上,此时仅对该方法生效。要确保该方法是 public 的,因为 Spring AOP 基于代理模式,默认情况下,只有 public 方法才会被代理增强。

若将注解放在类上,意味着该类中的所有 public 方法都会启用事务管理。不过,要注意如果类中有部分方法不需要事务,这种方式可能会带来不必要的事务开销。

2.异常处理与回滚规则

默认回滚规则:@Transactional 默认只对 RuntimeException 及其子类和 Error 进行回滚。如果业务代码中抛出的是受检异常(如 IOException),默认情况下事务不会回滚。

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;@Service
public class UserService {@Transactionalpublic void saveUser() throws IOException {// 业务逻辑throw new IOException("文件操作异常"); // 默认不回滚}
}

自定义回滚规则:可通过 rollbackFornoRollbackFor 属性来指定需要回滚和不需要回滚的异常类型。

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;@Service
public class UserService {@Transactional(rollbackFor = {IOException.class})public void saveUser() throws IOException {// 业务逻辑throw new IOException("文件操作异常"); // 会回滚}
}

 3. 事务传播行为和隔离级别

合理选择传播行为:传播行为定义了事务方法如何与当前事务进行交互,有 REQUIREDSUPPORTSMANDATORY 等多种传播行为。例如,REQUIRED 是最常用的传播行为,若当前存在事务则加入,不存在则创建新事务;而 SUPPORTS 表示若当前存在事务则加入,不存在则以非事务方式执行。要根据业务需求合理选择,避免不必要的事务嵌套。

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {@Transactional(propagation = Propagation.REQUIRED)public void saveUser() {// 业务逻辑}
}

隔离级别定义了一个事务对其他事务的可见性,有 READ_UNCOMMITTEDREAD_COMMITTEDREPEATABLE_READSERIALIZABLE 等。过高的隔离级别会增加事务的并发控制开销,要根据业务需求选择合适的隔离级别,如大多数场景使用 READ_COMMITTED 即可。

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {@Transactional(isolation = Isolation.READ_COMMITTED)public void saveUser() {// 业务逻辑}
}

4. 代理机制

内部方法调用问题

同一类内方法调用:Spring AOP 基于代理模式,当在同一个类的一个无事务方法中调用有 @Transactional 注解的方法时,事务不会生效。因为这种调用没有经过代理对象,而是直接调用目标对象的方法。

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {public void nonTransactionalMethod() {this.transactionalMethod(); // 事务不生效}@Transactionalpublic void transactionalMethod() {// 业务逻辑}
}

 可以通过注入自身代理对象来解决,或者将有事务的方法提取到另一个服务类中。

5. 数据源和事务管理器配置

确保数据源与事务管理器匹配:要保证数据源和事务管理器的配置正确且相互匹配。如果使用多个数据源,需要为每个数据源配置相应的事务管理器,并在 @Transactional 注解中指定使用的事务管理器。

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {@Transactional("transactionManager2")public void saveUser() {// 业务逻辑}
}

6. 缩小事务范围,减少事务持有时间:尽量将不需要事务的操作放在事务之外执行,缩小事务的范围,减少事务持有锁的时间,从而提高并发性能。例如,先进行查询操作,再将需要事务的更新操作放在事务方法中。

4.3 两种方式的对比

编程式事务管理声明式事务管理
代码耦合度高,事务管理代码与业务逻辑代码紧密耦合低,事务管理代码与业务逻辑代码分离
灵活性高,可以在代码中根据具体情况灵活控制事务的开始、提交和回滚相对较低,主要通过注解配置事务属性
可维护性低,事务管理代码分散在业务逻辑代码中,维护困难高,事务管理代码集中在注解中,易于维护
适用场景适用于事务管理逻辑复杂,需要根据具体情况灵活控制事务的场景适用于大多数业务场景,特别是事务管理逻辑相对简单的场景

综上所属,编程式事务管理适合复杂的事务处理场景,而声明式事务管理则更适合事务逻辑相对简单、需要提高开发效率和降低代码耦合度的场景。在实际开发中,可以根据具体需求选择合适的事务管理方式。


http://www.ppmy.cn/devtools/158694.html

相关文章

本地部署【LLM-deepseek】大模型 ollama+deepseek/conda(python)+openwebui/docker+openwebui

通过ollama本地部署deepseek 总共两步 1.模型部署 2.[web页面] 参考官网 ollama:模型部署 https://ollama.com/ open-webui:web页面 https://github.com/open-webui/open-webui 设备参考 Mac M 芯片 windows未知 蒸馏模型版本:deepseek-r1:14b 运行情况macminim2 24256 本地…

在亚马逊云科技上一键自动部署Falcon3大语言模型

由TII(阿布扎比技术创新研究所)开发的全新的Falcon 3系列模型,已经在亚马逊云科技的模型自动化快速部署功能 - Amazon SageMaker JumpStart上可以使用了。在本文中小李哥就将带大家探训如何在Amazon SageMaker AI上高效部署Falcon3模型。 Fa…

讲解一下SpringBoot的RPC连接

Spring Boot 本身并不直接提供 RPC(Remote Procedure Call,远程过程调用)功能,但可以通过集成其他框架或库来实现 RPC 通信。常见的 RPC 框架包括 Dubbo、gRPC、Thrift、Spring Cloud 等。下面我将讲解如何在 Spring Boot 中集成和…

ChartDB:一个基于Web的可视化数据库设计工具

这次给大家介绍一个可视化的数据库设计工具:ChartDB。 ChartDB 是一个免费开源的数据库可视化设计工具,支持的数据库包括 MySQL、MariaDB、PostgreSQL、Microsoft SQL Server、SQLite、ClickHouse 等。 对于已有的数据库,ChartDB 提供了一键…

【生产变更】- 19c ADG failover

【生产变更】- 19c ADG failover 一、概述二、操作步骤2.1 备库停止mrp2.2 备库进行failover2.3 新主库置为open状态2.4 确认新主库数据库角色 一、概述 Failover场景通常在主库突发故障(如硬件故障、数据库故障、操作系统故障等),短时间无法…

爬虫JS逆向 - 从入门到实战

第一章:JS逆向的基础知识 1.1 什么是JS逆向 JS逆向(JavaScript Reverse Engineering)是指通过分析前端JavaScript代码,提取其中的数据逻辑、API请求、加密方式等信息的过程。其目的是绕过前端的动态加载机制,直接获取我们需要的数据。 1.2 动态网页的工作原理 传统的静…

嵌入式linux下如何通过IIS接口驱动实现录制pcm音频

在嵌入式 Linux 下,通常使用 ALSA(Advanced Linux Sound Architecture)而不是 IIS(Internet Information Services,它主要用于 Windows 上的 Web 服务,这里你可能想说的是 I2S,Inter - Integrat…

Day1:强化学习基本概念

一、基本概念 1. Agent 智能体:执行动作的对象 2. State 状态:对当前环境的概括 3. Action 动作:智能体基于当前状态做出的决策 4. Reward 奖励:智能体执行完一个动作后,环境反馈给智能体的一个数值。(…