spring事务中同一connection的保证依赖datasourceutils与threadlocal绑定机制,而非连接池本身;事务开启时connection被绑定到当前线程,后续操作复用该连接,结束后归还至连接池而非关闭。

Spring 事务中能保证同一个 Connection,核心不是靠连接池本身,而是靠 DataSourceUtils 和底层的 ThreadLocal 绑定机制 协同工作。连接池(如 HikariCP)只负责创建、复用、回收物理连接;真正让“一个事务内所有 DAO 操作共享同一连接”的,是 Spring 的事务同步管理器(TransactionSynchronizationManager)和 DataSourceUtils 的配合。
DataSourceUtils.getConnection() 怎么找连接
它不是每次都向连接池要新连接,而是先查当前线程是否已有事务绑定的 Connection:
- 调用
TransactionSynchronizationManager.getResource(dataSource),从当前线程的 ThreadLocal 中查找是否已存有该数据源对应的 ConnectionHolder - 如果找到且有效(hasConnection 为 true),直接返回这个 Connection —— 这就是事务内复用的同一个连接
- 如果没找到,才通过
dataSource.getConnection()向连接池申请一个新连接,并自动绑定到当前线程(同时注册同步回调)
事务开启时 Connection 就被“预订”了
当你在 service 方法上加 @Transactional,Spring AOP 在方法执行前触发事务拦截器,会:
- 创建事务上下文,调用
doBegin() - 从连接池获取一个 Connection,并通过
TransactionSynchronizationManager.bindResource()把它存进当前线程的 ThreadLocal - 设置
autoCommit = false,并可能设置隔离级别、只读标志等
此后,无论你在该方法里调用多少次 jdbcTemplate.query() 或自定义 DAO,只要走的是 DataSourceUtils.getConnection()(JdbcTemplate 默认就用它),拿到的都是这个已绑定的 Connection。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
事务结束时 Connection 不会被真关闭
事务提交或回滚后,Spring 会:
- 调用
TransactionSynchronizationManager.unbindResource(),把 Connection 从 ThreadLocal 中移除 - 但不会调用
connection.close()—— 而是调用DataSourceUtils.releaseConnection(conn, dataSource) - 这个 release 方法对连接池来说,只是“归还连接”,不是销毁;连接继续回到池中等待下次复用
为什么手动 new Connection 会破坏事务
如果你在 @Transactional 方法里绕过 Spring,直接写:
Connection conn = DriverManager.getConnection(...);那这个 conn 完全不受 Spring 管理:
- 不经过 DataSourceUtils,不进 ThreadLocal
- 事务提交时不会影响它,也不会自动 rollback
- 它和事务内的其他操作根本不在同一个 Connection 上,自然无法参与统一事务
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










