news 2026/4/25 9:56:54

Spring事务

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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绑定的资源不会自动传递到子线程,

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/19 1:57:38

1000人网络设计冗余型

只做到DHCP中继服务了&#xff0c;还有电信的pppoe拨号上网、telnet、策略路由等还没做&#xff0c;等下次更新&#xff0c;配置需要对照拓扑图来看<HX_SW1>dis cu # sysname HX_SW1 # undo info-center enable # vlan batch 2 to 5 200 800 999 # stp instance 1 root …

作者头像 李华
网站建设 2026/4/25 9:56:50

PyCausalSim:基于模拟的因果发现的Python框架

做 A/B 测试或者分析转化率的时候&#xff0c;经常会碰到那个老生常谈的问题&#xff1a; “这数据的波动到底是干预引起的&#xff0c;还是仅仅是相关性&#xff1f;” 传统的分析手段和机器学习擅长告诉你什么能预测结果&#xff0c;但预测不等于因果。而在做决策&#xff…

作者头像 李华
网站建设 2026/4/15 11:37:09

技术工具类文章仿写专家Prompt指南

技术工具类文章仿写专家Prompt指南 【免费下载链接】LeagueAkari ✨兴趣使然的&#xff0c;功能全面的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/LeagueAkari 一、核心任务定义 你是一名专业的文章仿…

作者头像 李华
网站建设 2026/4/18 2:28:54

终极指南:5步实现B站视频高效批量下载与高清保存

终极指南&#xff1a;5步实现B站视频高效批量下载与高清保存 【免费下载链接】downkyi 哔哩下载姬downkyi&#xff0c;哔哩哔哩网站视频下载工具&#xff0c;支持批量下载&#xff0c;支持8K、HDR、杜比视界&#xff0c;提供工具箱&#xff08;音视频提取、去水印等&#xff09…

作者头像 李华
网站建设 2026/4/23 21:32:11

2024年8月中文大模型战力榜:国产模型全面崛起改写全球竞争格局

一、行业背景与研究意义 【免费下载链接】DeepSeek-V2-Chat-0628 DeepSeek-V2-Chat-0628&#xff0c;开源创新之作&#xff0c;AI聊天机器人性能卓越&#xff0c;编码能力出众。在LMSYS Chatbot Arena榜单脱颖而出&#xff0c;多项任务表现领先。升级优化&#xff0c;体验更佳&…

作者头像 李华
网站建设 2026/4/24 7:51:01

LeetCode热题100--215. 数组中的第K个最大元素--中等

题目 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1: 输入: [3,2,1,5,6,4]…

作者头像 李华