requires_new确实新建事务,但前提是先挂起当前事务:若存在活动事务则解绑并备份其connection及状态,新建独立事务执行,结束后恢复原事务上下文。

<p>在手写事务管理器中实现 <strong>REQUIRES_NEW</strong> 传播行为并挂起当前连接,核心在于:**主动解绑当前线程的事务资源(如 Connection),开启独立新事务,并在新事务结束后恢复旧事务上下文**。这不是靠数据库或框架自动完成,而是靠你对线程局部变量(ThreadLocal)和连接生命周期的精确控制。</p> <h3>1. 用 ThreadLocal 管理事务上下文栈</h3> <p>不能只存单个 Connection,而要维护一个“事务上下文栈”,每层对应一次事务调用(尤其是嵌套时)。每个上下文包含:<strong>Connection、是否为新事务、是否已提交/回滚、挂起前的旧上下文引用</strong>。</p>
- 进入 REQUIRES_NEW 前,先获取当前栈顶上下文(若有),将其状态设为“已挂起”
- 将当前 Connection(如有)从 ThreadLocal 中移除(即解绑),避免被新事务复用
- 新建 Connection,开启新事务,压入新上下文到栈顶
2. 挂起的本质是“解绑 + 备份”
挂起不是暂停连接,而是切断当前线程与已有 Connection 的绑定关系,并保存其状态以便恢复。关键操作:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- connection.setAutoCommit(false) 后,不能直接 close;必须保留它,但不留在 ThreadLocal 中
- 把原 Connection 和其事务状态(如 isolation level、readOnly 标志)封装进一个
SuspendedTransaction对象 - 将该对象存入新上下文的
suspendedContext字段,而不是丢弃
3. 新事务执行完必须显式恢复
新事务 commit/rollback 后,不能直接清空 ThreadLocal,而要检查是否有挂起上下文:
- 若存在挂起上下文,将其重新 set 到 ThreadLocal,恢复 Connection 绑定
- 重置 connection.setAutoCommit(false),并按原状态恢复 isolation level 等属性
- 注意:恢复后不能再次 commit —— 原事务的 commit 应由最外层调用者决定
4. 避免常见陷阱
手写时容易出错的地方:
- 没用栈结构,导致多层 REQUIRES_NEW 嵌套时恢复错层(比如内层 rollback 影响外层)
- 挂起时只备份 Connection,没备份 autoCommit/isolation/readOnly 状态,恢复后行为异常
- 新事务抛异常未正确 rollback 挂起的旧连接,造成连接泄漏或脏数据
- 忘记在 finally 块中恢复上下文,导致后续调用拿到错误的 Connection
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










