Spring - 事务管理
一、Spring 事务概览1.1 什么是 Spring 事务管理Spring 事务管理是对数据库事务的抽象封装通过 AOP 实现声明式事务让开发者无需手动编写Connection.setAutoCommit(false)/commit()/rollback()等代码。Spring 提供两种事务管理方式方式说明使用场景声明式事务基于 AOP通过注解或 XML 配置绝大多数场景编程式事务手动控制事务边界需要细粒度控制的场景1.2 Spring 事务抽象架构底层资源具体实现Spring事务抽象层应用层数据库连接DataSourceTransactionManagerJpaTransactionManagerJtaTransactionManagerPlatformTransactionManager事务管理器接口TransactionDefinition事务定义TransactionStatus事务状态业务代码Transactional 注解核心三接口接口作用PlatformTransactionManager事务管理器负责获取事务、提交、回滚TransactionDefinition定义事务属性传播、隔离、超时、只读TransactionStatus事务运行状态可查询是否新事务、是否已完成public interface PlatformTransactionManager { TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; void commit(TransactionStatus status) throws TransactionException; void rollback(TransactionStatus status) throws TransactionException; }1.3 Transactional 注解属性Transactional( propagation Propagation.REQUIRED, // 传播行为默认 REQUIRED isolation Isolation.DEFAULT, // 隔离级别默认 DEFAULT使用数据库默认 timeout -1, // 超时时间秒默认 -1无超时 readOnly false, // 是否只读默认 false rollbackFor {}, // 指定回滚异常数组 noRollbackFor {}, // 指定不回滚异常数组 transactionManager , // 指定事务管理器 label {} // 事务标签 )默认回滚策略只有RuntimeException和Error触发回滚受检异常checked exception不回滚。这是面试高频考点。二、Transactional 原理2.1 整体原理AOP ThreadLocalTransactional本质是一个 AOP 切面Spring 在 Bean 创建阶段通过AutoProxyCreator为标注了Transactional的 Bean 创建代理对象。不存在已存在RuntimeException/Errorchecked exception正常返回调用代理对象方法是否存在事务?开启事务conn.setAutoCommit false根据传播行为决定加入/挂起/新建执行目标方法是否抛出异常?回滚 rollback提交 commit2.2 核心源码TransactionInterceptor事务切面的核心是TransactionInterceptor它实现了MethodInterceptor接口// org.springframework.transaction.interceptor.TransactionInterceptor public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable { Override Nullable public Object invoke(MethodInvocation invocation) throws Throwable { Class? targetClass invocation.getThis() ! null ? AopUtils.getTargetClass(invocation.getThis()) : null; // 调用父类 TransactionAspectSupport 的核心方法 return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); } }真正的逻辑在父类TransactionAspectSupport.invokeWithinTransaction()中// org.springframework.transaction.interceptor.TransactionAspectSupport protected Object invokeWithinTransaction(Method method, Nullable Class? targetClass, InvocationCallback invocation) throws Throwable { TransactionAttributeSource tas getTransactionAttributeSource(); final TransactionAttribute txAttr tas.getTransactionAttribute(method, targetClass); final PlatformTransactionManager tm determineTransactionManager(txAttr); // 1. 解析事务名称 final String joinpointIdentification methodIdentification(method, targetClass, txAttr); // 2. 声明式事务处理注解方式 if (txAttr null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { TransactionInfo txInfo createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal; try { // 3. 执行目标方法 retVal invocation.proceedWithInvocation(); } catch (Throwable ex) { // 4. 异常处理 - 判断是否需要回滚 completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { // 5. 清理事务信息 cleanupTransactionInfo(txInfo); } // 6. 正常返回 - 提交事务 commitTransactionAfterReturning(txInfo); return retVal; } // ... 编程式事务处理CallbackPreferringPlatformTransactionManager }2.3 事务如何绑定到线程ThreadLocalSpring 通过ThreadLocal将数据库连接绑定到当前线程保证同一线程内多次数据库操作使用同一个 Connection// org.springframework.transaction.support.TransactionSynchronizationManager public abstract class TransactionSynchronizationManager { // 用 ThreadLocal 保存当前线程的事务资源如 Connection private static final ThreadLocalMapObject, Object resources new NamedThreadLocal(Transactional resources); // 用 ThreadLocal 保存当前线程的事务同步回调 private static final ThreadLocalSetTransactionSynchronization synchronizations new NamedThreadLocal(Transaction synchronizations); // 用 ThreadLocal 保存当前事务的名称 private static final ThreadLocalString currentTransactionName new NamedThreadLocal(Current transaction name); // 用 ThreadLocal 保存当前事务是否只读 private static final ThreadLocalBoolean currentTransactionReadOnly new NamedThreadLocal(Current transaction read-only status); // 用 ThreadLocal 保存事务隔离级别 private static final ThreadLocalInteger currentTransactionIsolationLevel new NamedThreadLocal(Current transaction isolation level); // 用 ThreadLocal 保存事务是否活跃 private static final ThreadLocalBoolean actualTransactionActive new NamedThreadLocal(Actual transaction active); }Thread-0ThreadLocalConnection-1autoCommitfalseThread-1ThreadLocalConnection-2autoCommitfalseThread-2ThreadLocal无事务autoCommittrue关键点事务绑定在ThreadLocal上意味着事务只能在同一个线程内传播。如果方法内部通过new Thread()或线程池执行数据库操作新线程不会继承事务。2.4 createTransactionIfNecessary 核心流程// TransactionAspectSupport#createTransactionIfNecessary protected TransactionInfo createTransactionIfNecessary( PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) { // 如果没有指定事务名称使用方法标识 if (txAttr.getName() null) { txAttr new DelegatingTransactionAttribute(txAttr) { Override public String getName() { return joinpointIdentification; } }; } TransactionStatus status null; if (txAttr null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // 核心入口根据事务定义获取/创建事务 status tm.getTransaction(txAttr); } return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); }getTransaction()由AbstractPlatformTransactionManager实现核心逻辑是根据传播行为决定事务的处理方式// org.springframework.transaction.support.AbstractPlatformTransactionManager public final TransactionStatus getTransaction(Nullable TransactionDefinition definition) throws TransactionException { TransactionDefinition def (definition ! null ? definition : TransactionDefinition.withDefaults()); Object transaction doGetTransaction(); boolean debugEnabled logger.isDebugEnabled(); // 已存在事务时的处理 if (isExistingTransaction(transaction)) { return handleExistingTransaction(def, transaction, debugEnabled); } // 检查超时设置 if (def.getTimeout() TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException(Invalid transaction timeout, def.getTimeout()); } // 当前没有事务根据传播行为处理 // MANDATORY: 必须有事务没有则抛异常 if (def.getPropagationBehavior() TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException(No existing transaction found for MANDATORY); } // REQUIRED / REQUIRES_NEW / NESTED: 没有事务则新建 else if (def.getPropagationBehavior() TransactionDefinition.PROPAGATION_REQUIRED || def.getPropagationBehavior() TransactionDefinition.PROPAGATION_REQUIRES_NEW || def.getPropagationBehavior() TransactionDefinition.PROPAGATION_NESTED) { SuspendedResourcesHolder suspendedResources suspend(null); try { boolean newSynchronization (getTransactionSynchronization() ! SYNCHRONIZATION_NEVER); DefaultTransactionStatus status newTransactionStatus( def, transaction, true, newSynchronization, debugEnabled, suspendedResources); // 开启事务如 connection.setAutoCommit(false) doBegin(transaction, def); prepareSynchronization(status, def); return status; } catch (RuntimeException | Error ex) { resume(null, suspendedResources); throw ex; } } else { // SUPPORTS / NOT_SUPPORTED / NEVER: 非事务方式执行 boolean newSynchronization (getTransactionSynchronization() SYNCHRONIZATION_ALWAYS); return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null); } }三、事务传播机制3.1 七种传播行为有事务时的行为REQUIRED加入当前事务SUPPORTS加入当前事务MANDATORY加入当前事务REQUIRES_NEW挂起旧事务创建新事务NOT_SUPPORTED挂起当前事务非事务执行NEVER抛出异常NESTED创建嵌套事务savepoint传播行为外层无事务外层有事务使用频率REQUIRED默认新建事务加入外层事务⭐⭐⭐⭐⭐REQUIRES_NEW新建事务挂起外层新建独立事务⭐⭐⭐⭐NESTED新建事务创建嵌套事务savepoint⭐⭐⭐SUPPORTS非事务执行加入外层事务⭐⭐⭐NOT_SUPPORTED非事务执行挂起外层非事务执行⭐⭐MANDATORY抛出异常加入外层事务⭐⭐NEVER非事务执行抛出异常⭐3.2 REQUIRED vs REQUIRES_NEW vs NESTED高频对比flowchart TD A[外层方法 Transactional] -- B[内层方法] B -- C{传播行为} C --|REQUIRED| D[内外层共用同一个事务br/一起提交/回滚] C --|REQUIRES_NEW| E[挂起外层事务br/内层独立事务br/内层异常不影响外层] C --|NESTED| F[创建 savepointbr/内层回滚到 savepointbr/外层事务不受影响]代码示例Service public class OrderService { Autowired private OrderMapper orderMapper; Autowired private LogService logService; Transactional public void createOrder(Order order) { orderMapper.insert(order); logService.recordLog(order.getId()); } } Service public class LogService { Transactional(propagation Propagation.REQUIRES_NEW) public void recordLog(Long orderId) { // 即使外层回滚日志也会提交 } }REQUIRED 场景分析Service public class UserService { Autowired private UserService self; // 注入代理对象 Transactional public void methodA() { // methodB 和 methodC 在同一个事务中 self.methodB(); self.methodC(); // methodC 抛异常整个事务回滚methodB 的操作也回滚 } Transactional public void methodB() { // 操作数据库 } Transactional public void methodC() { throw new RuntimeException(出错了); } }REQUIRES_NEW 场景分析Service public class UserService { Transactional public void methodA() { // 操作1 self.methodB(); // REQUIRES_NEW 独立事务正常提交 // 操作2 throw new RuntimeException(); // 只有 methodA 的事务回滚methodB 不受影响 } Transactional(propagation Propagation.REQUIRES_NEW) public void methodB() { // 独立事务独立提交/回滚 } }3.3 REQUIRES_NEW 的底层原理// AbstractPlatformTransactionManager#handleExistingTransaction关键片段 case TransactionDefinition.PROPAGATION_REQUIRES_NEW: // 1. 挂起当前事务 SuspendedResourcesHolder suspendedResources suspend(transaction); try { boolean newSynchronization (getTransactionSynchronization() ! SYNCHRONIZATION_NEVER); DefaultTransactionStatus status newTransactionStatus( def, transaction, true, newSynchronization, debugEnabled, suspendedResources); // 2. 开启全新事务从连接池获取新的 Connection doBegin(transaction, def); prepareSynchronization(status, def); return status; } catch (RuntimeException | Error beginEx) { // 3. 新事务开启失败恢复挂起的事务 resume(null, suspendedResources); throw beginEx; }关键点suspend()会将当前事务的资源Connection从 ThreadLocal 解绑并保存然后doBegin()从数据源获取新的 Connection 绑定到 ThreadLocal。3.4 NESTED 嵌套事务原理case TransactionDefinition.PROPAGATION_NESTED: if (useSavepointForNestedTransaction()) { // 默认使用 savepoint 方式 DefaultTransactionStatus status prepareTransactionStatus( def, transaction, false, false, debugEnabled, null); // 创建 savepoint status.createAndHoldSavepoint(); return status; } else { // JTA 事务管理器可能不支持 savepoint使用新建事务 return handleExistingTransaction(def, transaction, debugEnabled); }NESTED 与 REQUIRES_NEW 的区别NESTED 是同一个物理事务中的 savepoint回滚只回滚到 savepointREQUIRES_NEW 是完全独立的新事务使用不同的 Connection。四、事务隔离级别4.1 四种隔离级别隔离级别脏读不可重复读幻读性能READ_UNCOMMITTED可能可能可能最高READ_COMMITTED不可能可能可能高REPEATABLE_READMySQL默认不可能不可能可能中SERIALIZABLE不可能不可能不可能最低4.2 Spring 隔离级别与数据库隔离级别关系public interface TransactionDefinition { int ISOLATION_DEFAULT -1; // 使用数据库默认隔离级别 int ISOLATION_READ_UNCOMMITTED 1; // 对应 Connection.TRANSACTION_READ_UNCOMMITTED int ISOLATION_READ_COMMITTED 2; // 对应 Connection.TRANSACTION_READ_COMMITTED int ISOLATION_REPEATABLE_READ 4; // 对应 Connection.TRANSACTION_REPEATABLE_READ int ISOLATION_SERIALIZABLE 8; // 对应 Connection.TRANSACTION_SERIALIZABLE }注意Spring 的隔离级别最终会映射为java.sql.Connection的常量。当设置ISOLATION_DEFAULT时使用数据库自身的默认隔离级别MySQL 默认REPEATABLE_READPostgreSQL 默认READ_COMMITTED。4.3 readOnly 属性Transactional(readOnly true)作用语义声明告诉开发者和管理员这是一个只读操作优化提示Spring 会向 JDBC Driver 发送readOnly提示部分驱动会做优化如 MySQL InnoDB 对只读事务不做 change buffer异常检查部分 JPA Provider如 Hibernate在readOnlytrue时会跳过脏检查提升查询性能注意readOnly只适用于REQUIRED和REQUIRES_NEW传播行为对其他传播行为无效。五、事务失效场景重点5.1 事务失效的 7 大场景mindmap root((事务失效场景)) 自调用问题 同类方法内部调用 未通过代理对象调用 异常类型错误 捕获了异常未抛出 抛出的是 checked exception 方法修饰符问题 方法是 private 方法是 final 方法是 static 非public方法 protected / package-private 异常被吞掉 try-catch 未抛出 未设置 rollbackFor 多线程调用 新线程无法继承事务 传播行为不对 NOT_SUPPORTED NEVER 数据库引擎不支持 MyISAM 不支持事务5.2 场景一自调用最常见Service public class UserService { // ❌ 事务失效内部调用不经过代理 public void batchInsert() { this.insertUser(张三); this.insertUser(李四); // 异常后张三已经插入无法回滚 } Transactional public void insertUser(String name) { userMapper.insert(name); if (李四.equals(name)) { throw new RuntimeException(); } } }原因batchInsert()内部通过this调用insertUser()绕过了代理对象Transactional切面没有生效。解决方案Service public class UserService { Autowired private UserService self; // 注入自身的代理对象 // ✅ 通过代理对象调用事务生效 public void batchInsert() { self.insertUser(张三); self.insertUser(李四); } Transactional public void insertUser(String name) { userMapper.insert(name); if (李四.equals(name)) { throw new RuntimeException(); } } }原理Spring AOP 的代理对象拦截方法调用this.insertUser()直接调用目标对象不经过代理。self.insertUser()通过注入的代理对象调用会被TransactionInterceptor拦截。5.3 场景二异常被捕获Service public class UserService { // ❌ 事务失效异常被 try-catch 吞掉了 Transactional public void createUser(String name) { try { userMapper.insert(name); int i 1 / 0; } catch (Exception e) { log.error(创建用户失败, e); // 异常被吞掉TransactionInterceptor 看不到异常执行 commit } } }解决方案// 方案1抛出异常 Transactional public void createUser(String name) { try { userMapper.insert(name); int i 1 / 0; } catch (Exception e) { log.error(创建用户失败, e); throw e; // 重新抛出让 TransactionInterceptor 处理 } } // 方案2手动标记回滚 Transactional public void createUser(String name) { try { userMapper.insert(name); int i 1 / 0; } catch (Exception e) { log.error(创建用户失败, e); TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } }5.4 场景三抛出的是 checked exceptionService public class UserService { // ❌ 事务失效IOException 是 checked exception默认不回滚 Transactional public void createUser(String name) throws IOException { userMapper.insert(name); throw new IOException(文件写入失败); } }解决方案// 方案1指定 rollbackFor Transactional(rollbackFor Exception.class) public void createUser(String name) throws IOException { userMapper.insert(name); throw new IOException(文件写入失败); } // 方案2指定具体的异常类 Transactional(rollbackFor {IOException.class, SQLException.class}) public void createUser(String name) throws IOException { userMapper.insert(name); throw new IOException(文件写入失败); }最佳实践建议所有Transactional都显式指定rollbackFor Exception.class避免踩坑。5.5 场景四方法不是 publicService public class UserService { // ❌ 事务失效Transactional 只能用于 public 方法 Transactional void createUser(String name) { userMapper.insert(name); } }原因Spring AOP 默认只拦截public方法。在AbstractFallbackTransactionAttributeSource中有检查// TransactionAttributeSource 的查找逻辑 if (allowPublicMethodsOnly() !Modifier.isPublic(method.getModifiers())) { return null; // 非 public 方法返回 null表示没有事务属性 }5.6 场景五方法是 final 或 staticService public class UserService { // ❌ 事务失效final 方法不能被重写CGLIB 代理无法生效 Transactional public final void createUser(String name) { userMapper.insert(name); } // ❌ 事务失效static 方法不属于对象实例无法被代理 Transactional public static void staticMethod() { // ... } }原因CGLIB 通过生成子类重写方法实现代理final方法无法被重写static方法属于类而非实例无法被 AOP 拦截。5.7 场景六未被 Spring 管理// ❌ 事务失效没有加 Component/Service 等注解 public class UserService { Transactional public void createUser(String name) { userMapper.insert(name); } }原因类没有被 Spring 容器管理自然不会被 AOP 代理。5.7 场景七数据库引擎不支持事务-- MySQL 的 MyISAM 引擎不支持事务 CREATE TABLE user ( id BIGINT PRIMARY KEY, name VARCHAR(50) ) ENGINEMyISAM; -- 必须使用 InnoDB 引擎 CREATE TABLE user ( id BIGINT PRIMARY KEY, name VARCHAR(50) ) ENGINEInnoDB;5.8 事务失效场景速查表序号场景是否失效解决方案1自调用this.method()❌ 失效注入 self 代理对象调用2异常被 try-catch 吞掉❌ 失效重新抛出或 setRollbackOnly()3抛出 checked exception❌ 失效rollbackFor Exception.class4方法不是 public❌ 失效改为 public5方法是 final❌ 失效去掉 final6方法是 static❌ 失效去掉 static7类未被 Spring 管理❌ 失效加 Service/Component8数据库引擎不支持❌ 失效使用 InnoDB9传播行为为 NOT_SUPPORTED❌ 失效修改传播行为10多线程调用❌ 失效使用编程式事务或消息队列六、编程式事务6.1 TransactionTemplateService public class UserService { Autowired private TransactionTemplate transactionTemplate; Autowired private UserMapper userMapper; public void createUser(String name) { transactionTemplate.execute(status - { try { userMapper.insert(name); // 其他操作... return true; } catch (Exception e) { status.setRollbackOnly(); // 标记回滚 return false; } }); } }6.2 PlatformTransactionManager 手动控制Service public class UserService { Autowired private PlatformTransactionManager transactionManager; public void createUser(String name) { DefaultTransactionDefinition def new DefaultTransactionDefinition(); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); TransactionStatus status transactionManager.getTransaction(def); try { userMapper.insert(name); transactionManager.commit(status); } catch (Exception e) { transactionManager.rollback(status); throw e; } } }6.3 声明式 vs 编程式对比项声明式事务编程式事务实现方式AOP 代理手动编码代码侵入低高粒度控制方法级别代码块级别可读性高低使用场景绝大多数场景需要细粒度控制七、自检Q1: Transactional 的底层原理基于 AOP ThreadLocal 实现。 1. Spring 启动时通过 AutoProxyCreator 为标注 Transactional 的 Bean 创建代理对象 2. 调用方法时代理对象的 TransactionInterceptor 拦截调用 3. 从 TransactionAttributeSource 解析事务属性传播、隔离、超时等 4. 通过 PlatformTransactionManager 获取/创建事务ThreadLocal 绑定 Connection 5. 执行目标方法 6. 正常返回则提交抛出 RuntimeException/Error 则回滚 7. finally 中清理 ThreadLocal 中的事务信息Q2: Spring 事务传播机制有哪些最常用的是哪几个共 7 种传播行为 最常用的 3 个 - REQUIRED默认有事务就加入没有就新建。绝大多数场景使用 - REQUIRES_NEW总是新建独立事务挂起外层事务。用于记录日志等独立操作 - NESTED嵌套事务基于 savepoint。内层回滚不影响外层 其他 4 个 - SUPPORTS有事务就加入没有就非事务执行 - NOT_SUPPORTED非事务执行挂起当前事务 - MANDATORY必须在事务中调用否则抛异常 - NEVER必须不在事务中调用否则抛异常Q3: REQUIRED 和 REQUIRES_NEW 的区别核心区别 1. REQUIRED内外层共用同一个物理事务同一个 Connection - 内层回滚 → 外层也回滚 - 外层回滚 → 内层也回滚 2. REQUIRES_NEW挂起外层事务创建新的独立事务新 Connection - 内层回滚 → 不影响外层 - 外层回滚 → 不影响内层内层已独立提交 典型使用场景 - REQUIRES_NEW 适用于操作日志记录即使主业务回滚日志也要保留Q4: 说一下事务失效的场景最常见的几种 1. 自调用同一个类中非事务方法调用事务方法this 引用绕过了代理 2. 异常被吞try-catch 捕获异常后没有重新抛出 3. 异常类型不对checked exception 默认不回滚需要 rollbackFor Exception.class 4. 方法修饰符问题非 public、final、static 方法都无法被代理 5. 类未被 Spring 管理没有加 Service 等注解 6. 多线程新线程无法继承 ThreadLocal 中的事务 7. 数据库引擎MyISAM 不支持事务 解决方案 - 自调用 → 注入自身代理对象Autowired private XxxService self - checked exception → rollbackFor Exception.class - 其他 → 代码规范Q5: 为什么 checked exception 默认不回滚这是设计选择Spring 认为受检异常checked exception通常是业务可预期的异常 调用方已经通过 try-catch 处理了不应该触发事务回滚。 而 RuntimeException运行时异常通常是不可预期的系统错误 如 NullPointerException、IllegalArgumentException 等应该触发回滚。 但实际开发中建议统一指定 rollbackFor Exception.class 让所有异常都回滚避免踩坑。Q6: 事务和锁的关系事务Transaction和锁Lock是两个不同层面的概念 - 事务保证一组操作的原子性要么全成功要么全失败 - 锁保证并发访问时数据的一致性 关系 - 事务依赖锁来实现隔离级别 - 在 REPEATABLE_READ 下MySQL 通过 MVCC Next-Key Lock 实现可重复读 - 事务持有锁的时间 从事务第一条 SQL 到事务结束commit/rollback - 事务时间越长持有锁的时间越长并发性能越差 所以事务应该尽量短避免长事务导致锁竞争。Q7: 如何避免长事务1. 不要在事务中做非数据库操作如 RPC 调用、文件操作、复杂计算 2. 不要在事务中查询大量数据 3. 将查询操作移到事务外部 4. 使用编程式事务缩小事务范围 5. 设置合理的超时时间 timeout 示例 // ❌ 长事务 Transactional public void order() { createOrder(); // DB操作 rpcCall(); // 网络调用可能耗时数秒 sendEmail(); // 发邮件可能耗时数秒 updateStock(); // DB操作 } // ✅ 短事务 public void order() { Order order createOrder(); rpcCall(); sendEmail(order); updateStockInTransaction(order); } Transactional public void updateStockInTransaction(Order order) { updateStock(); }核心源码路径速查类/方法作用TransactionInterceptor#invoke()事务切面入口拦截方法调用TransactionAspectSupport#invokeWithinTransaction()事务执行核心逻辑TransactionAspectSupport#createTransactionIfNecessary()创建/获取事务AbstractPlatformTransactionManager#getTransaction()根据传播行为决定事务处理AbstractPlatformTransactionManager#handleExistingTransaction()已有事务时的处理AbstractPlatformTransactionManager#suspend()挂起事务AbstractPlatformTransactionManager#commit()提交事务AbstractPlatformTransactionManager#rollback()回滚事务TransactionSynchronizationManager事务资源与线程绑定ThreadLocalDataSourceTransactionManager#doBegin()开启事务获取 ConnectionsetAutoCommit(false)