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

Spring中的事务是如何实现的

Spring框架提供了一套完整的事务管理机制,旨在简化事务处理,并确保数据操作的原子性、一致性、隔离性和持久性(ACID)。本文将详细介绍Spring事务管理的实现原理、配置方法和常见用法。

1. 事务的基本概念

事务(Transaction)是指一组操作,要么全部成功,要么全部失败。事务的四个关键特性是:

  • 原子性(Atomicity) :事务中的所有操作要么全部完成,要么全部不完成。
  • 一致性(Consistency) :事务执行前后,数据保持一致。
  • 隔离性(Isolation) :多个事务同时进行时,彼此独立。
  • 持久性(Durability) :事务一旦提交,对数据库的改变是永久性的。

2. Spring事务管理的实现原理

2.1. 事务管理器

Spring提供了多个事务管理器,用于处理不同的数据源,如 DataSourceTransactionManagerJpaTransactionManagerHibernateTransactionManager等。事务管理器负责管理事务的生命周期,包括开启、提交和回滚事务。

2.2. 事务传播行为

Spring定义了多种事务传播行为,决定了事务方法在调用其他事务方法时的事务处理方式。常见的传播行为包括:

  • REQUIRED:支持当前事务,如果不存在则创建一个新事务。
  • REQUIRES_NEW:创建一个新事务,如果存在当前事务,则将其挂起。
  • MANDATORY:支持当前事务,如果不存在则抛出异常。
  • SUPPORTS:支持当前事务,如果不存在则以非事务方式执行。
  • NOT_SUPPORTED:以非事务方式执行,如果存在当前事务,则将其挂起。
  • NEVER:以非事务方式执行,如果存在当前事务,则抛出异常。
  • NESTED:支持当前事务,并在其内嵌套一个子事务。

2.3. 事务隔离级别

事务隔离级别决定了一个事务能看见其他事务对数据库所做更改的程度。常见的隔离级别包括:

  • DEFAULT:使用底层数据库的默认隔离级别。
  • READ_UNCOMMITTED:允许读取未提交的数据,可能导致脏读。
  • READ_COMMITTED:只允许读取已提交的数据,防止脏读。
  • REPEATABLE_READ:确保在事务内多次读取数据一致,防止不可重复读。
  • SERIALIZABLE:最高隔离级别,完全锁定读写,防止幻读。

3. Spring事务管理的配置

3.1. 基于XML的配置

在Spring的XML配置文件中启用事务管理:

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!-- 配置数据源 --><bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"><!-- 配置数据源属性 --></bean><!-- 配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!-- 启用注解事务管理 --><tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
​

3.2. 基于Java的配置

在Spring的Java配置类中启用事务管理:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;@Configuration
@EnableTransactionManagement
public class AppConfig {@Beanpublic DataSource dataSource() {// 配置并返回数据源}@Beanpublic DataSourceTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}
​

4. 使用注解管理事务

4.1. @Transactional注解

Spring提供了 @Transactional注解,用于声明事务属性。该注解可以应用于类或方法上。

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

4.2. 自定义事务属性

可以在 @Transactional注解中指定传播行为、隔离级别、超时和回滚规则等属性。

import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE, timeout = 30, rollbackFor = Exception.class)public void createUser(User user) {// 执行数据库操作}
}
​

4.3. 使用AOP配置事务

除了注解方式,Spring还支持使用AOP(面向切面编程)配置事务管理。

定义切点和事务配置
<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="create*" 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:config><aop:pointcut id="serviceMethods" expression="execution(* com.example.service.*.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/>
</aop:config>
​
基于Java配置
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.interceptor.TransactionInterceptor;
import org.springframework.transaction.interceptor.TransactionProxyFactoryBean;import java.util.Properties;@Configuration
public class AopConfig {@Beanpublic TransactionInterceptor transactionInterceptor(PlatformTransactionManager transactionManager) {Properties properties = new Properties();properties.setProperty("create*", "PROPAGATION_REQUIRED");properties.setProperty("update*", "PROPAGATION_REQUIRED");properties.setProperty("delete*", "PROPAGATION_REQUIRED");properties.setProperty("*", "readOnly");TransactionInterceptor interceptor = new TransactionInterceptor();interceptor.setTransactionManager(transactionManager);interceptor.setTransactionAttributes(properties);return interceptor;}@Beanpublic ProxyFactoryBean userService(TransactionInterceptor transactionInterceptor) {ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();proxyFactoryBean.setTarget(new UserService());proxyFactoryBean.addAdvice(transactionInterceptor);return proxyFactoryBean;}
}
​

5. 事务管理的最佳实践

5.1. 避免事务嵌套

避免在同一事务方法中调用另一个事务方法,以防止事务传播行为不当引发的问题。

5.2. 适当设置超时

为长时间运行的事务设置合理的超时时间,防止锁定资源过长导致性能问题。

5.3. 细化事务范围

将事务范围限定在必要的代码块内,避免不必要的资源占用和性能开销。

5.4. 使用声明式事务

优先使用声明式事务管理(如 @Transactional注解),减少手动管理事务的复杂性和出错风险。

6. 事务管理的常见问题及解决方案

6.1. 事务不回滚

  • 确保捕获的异常是 @Transactional注解的 rollbackFor属性中指定的类型。
  • 检查方法调用是否在同一个类中,如果是,确保方法间调用通过Spring代理进行。

6.2. 事务传播行为不符合预期

  • 检查 @Transactional注解的 propagation属性,确保其设置符合业务逻辑。
  • 使用 Propagation.REQUIRES_NEW时,确保事务管理器支持此传播行为。

6.3. 数据库连接泄漏

  • 确保在事务管理器配置中正确设置数据源。
  • 检查应用程序中是否有未关闭的数据库连接。
http://www.xdnf.cn/news/16630.html

相关文章:

  • 非阿贝尔编织(Non-Abelian Braiding)
  • 【RAG Query Expansion论文解析】用 LLM 进行查询扩展 (Query Expansion)
  • CentOS 7 编译 Redis 6.x 完整教程(解决 GCC 版本不支持 C11)
  • 工业绝缘监测仪:保障工业电气安全的关键防线
  • AppAssember和maven-resources-plugin插件的使用
  • 订单识别与发票识别结合的技术实现方案
  • 运行图生视频/文生视频(Wan2.X等)的显卡配置总结
  • RabbitMQ 队列配置设置 RabbitMQ 消息监听器的并发消费者数量java
  • 深入剖析:C++ 手写实现 unordered_map 与 unordered_set 全流程指南
  • 【在线五子棋对战】十一、整合封装服务器模块实现
  • C++11特性——变量与初始化
  • 【React】fiber 架构
  • Jmeter 命令行压测、HTML 报告、Jenkins 配置目录
  • [特殊字符] 征服CPU的艺术:Rust多进程编程实战指南
  • 八股文场景题
  • Netty的Http解码器源码分析
  • (C++)C++类和类的方法(基础教程)(与Python类的区别)
  • LeetCode 刷题【22. 括号生成】
  • YOLO---01目标检测基础
  • C++提高编程学习--模板
  • 跳跃表可视化深度解析:动态演示数据结构核心原理
  • flutter 记录一个奇怪的问题
  • RAG实战指南 Day 28:RAG系统缓存与性能优化
  • ica1靶机攻略
  • 【 建模分析回顾】[MultiOutputClassifier]MAP - Charting Student Math Misunderstandings
  • Jaeger理论、实战、问题记录
  • UDP通讯和TCP通讯的区别-UDP(用户数据报协议)和 TCP(传输控制协议)
  • Docker-01.Docker课程介绍
  • 【25届数字IC秋招总结】面试经验12——海康威视
  • Rabbit MQ的消息模式-Java原生代码