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

Spring事务

学习资料:Spring 事务详解 | JavaGuide

Spring支持的事务本质上是数据库支持的事务,所以前提也是数据库支持事务

Spring不直接实现事务,而是通过事务管理器(PlatformTransactionManager)来对接不同底层技术:

底层技术对应的事务管理器
JDBC / MyBatisDataSourceTransactionManager
JPAJpaTransactionManager
HibernateHibernateTransactionManager

所以 Spring 的事务是抽象 + 适配的设计典范。

Spring支持两种方式的事务管理:编程式事务管理(使用硬编码的方式)和声明式事务管理(使用注解@Transactional的方式)

编程式事务:

@Autowired private PlatformTransactionManager transactionManager; public void save() { //1.开启事务 TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition()); try { // 业务代码 personDao.save(person); detailDao.save(detail); //2.提交 transactionManager.commit(status); } catch (Exception e) { //3.回滚 transactionManager.rollback(status); } } //这个是最原始的编程式事务:手动控制事务边界 //其实和直接用 JDBC 的 connection.setAutoCommit(false) + commit()/rollback() 是类似的,只是 Spring 把它抽象成了统一接口。 //TransactionTemplate 对 PlatformTransactionManager 的模板方法封装 @Autowired private TransactionTemplate transactionTemplate; public void save() { transactionTemplate.execute(status -> { // 业务代码 personDao.save(person); detailDao.save(detail); }); }

声明式事务:

@Service public class AccountService { @Transactional public void transfer(int from, int to, int amount) { accountDao.reduce(from, amount); // int i = 1/0; // 如果这里出异常,整个方法会回滚! accountDao.add(to, amount); } }

这种通过注解的方式底层原理实际是通过AOP 动态代理,在方法执行前后插入事务管理逻辑,底层调用PlatformTransactionManager实现编程式事务控制。

AOP通过给这个对象创建一个代理的方式拦截这个加了注解的方法,实际走的是代理的invoke方法。这个代理对象内部仍然持有真实对象的引用。

PlatformTransactionManager的底层原理

@Transactional public void transfer(...) { accountDao.reduce(...); // 第1次 DB 操作 accountDao.add(...); // 第2次 DB 操作 }

要保证原子性,同一个事务中的多次数据库操作必须使用同一个数据库连接,并且该连接处于手动提交模式

而默认情况下springboot中的datasource会自动配置一个最大连接为10的连接池

spring通过把connection绑定当当前线程(ThreadLocal)来实现使用同一个连接来保证事务操作:

在开启事务的时候,使用一个叫TransactionSynchronizationManager的工具类,内部通过ThreadLocal存储事务相关资源

@Override protected Object doGetTransaction() { DataSourceTransactionObject txObject = new DataSourceTransactionObject(); // 尝试从 ThreadLocal 中获取已存在的 Connection ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource); if (conHolder != null) { // 已有事务 → 复用 Connection(用于传播行为 REQUIRED) txObject.setConnectionHolder(conHolder, false); } else { // 新事务 → 从 DataSource 获取新连接 Connection con = dataSource.getConnection(); con.setAutoCommit(false); // 关键!关闭自动提交 // 绑定到当前线程的 ThreadLocal ConnectionHolder newConHolder = new ConnectionHolder(con); TransactionSynchronizationManager.bindResource(dataSource, newConHolder); txObject.setConnectionHolder(newConHolder, true); } return txObject; }

但是需要注意的是,ThreadLocal绑定的资源不会自动传递到子线程,

所以在异步任务、线程池等中,事务会失效,除非手动传递连接。

(这也是一次面试中面试官问到的,如果事务中开了一个子线程的话,事务还能生效吗)

http://www.cnnetsun.cn/news/27960.html

相关文章:

  • Day28~实现strlen、strcpy、strncpy、strcat、strncat
  • 空洞骑士模组管理大师课:5个关键技巧让Scarab成为你的游戏管家
  • 实用方法:轻松实现NCM文件格式转换的完整解析
  • C++课后习题训练记录Day49
  • LeetCode 189. 旋转数组 | 三步反转最优解全拆解
  • downkyi视频下载:告别卡顿与画质损失的终极解决方案
  • 教你如何玩转DPDK开发中的KNI与内核交互,让网络速度翻倍!
  • Openresty驱动下的高性能Web网关实战
  • 百度网盘下载工具终极指南:快速突破限速的完整教程
  • C语言实现hashmap(附带源码)
  • jsonnet介绍和使用
  • 喜马拉雅音频数据采集:API接口分析与加密音频链接解密实战
  • 角色影像生成新纪元:Pony V7-Base引领AI创作革命
  • 论文格式修改排名:9大平台+在线一键优化
  • 论文写作效率低?十大AI生成平台,AIGC降重+赶due不熬夜
  • 文献引用规范考核要点解析与实践指南
  • 文献综述写作期末指南:方法、结构与常见问题解析
  • 期末文献研究论文的撰写方法与实践路径探讨
  • 基于 HID 协议的扩展功能指令定义方案
  • 模拟IC设计:集成电路与运算放大器大观
  • 6、Oracle数据库管理:文件与目录操作全解析
  • 12、Oracle数据库Linux服务器软件管理全攻略
  • 某聘新版AST解混淆(青春版)
  • 基于Spring Boot框架和vue的的诗词鉴赏与交流网站的设计与实现_96fdvu1s
  • 基于模型预测算法的混合储能微电网双层能量管理系统研究(Matlab代码实现)
  • 三极管:电子信息时代的核心“控制单元”,藏于设备中的关键器件
  • 1小时打造专属右键菜单工具:快马平台实战
  • 零基础用AI制作第一个Macyy风格网页
  • GG3M业务核心:需求满足与问题解决 | GG3M Business Core: Demand Satisfaction and Problem Solving
  • 零基础玩转Vulhub:从安装到第一个漏洞复现