Java事务回滚核心是让事务管理机制感知异常并响应:Spring默认仅对RuntimeException和Error自动回滚,受检异常需用@Transactional(rollbackFor=...)显式配置;声明式、编程式及手动JDBC事务各有适用场景;多线程下事务不跨线程传递,需特殊处理协同回滚。

Java 中事务在发生异常时回滚,核心在于让事务管理机制“感知到异常并作出响应”。默认情况下,Spring 只对 RuntimeException 及其子类、Error 自动回滚;普通受检异常(如 IOException、SQLException、自定义 Exception)不会触发回滚,必须显式配置。
Spring 声明式事务:用 @Transactional 控制回滚
这是最常用、推荐的方式。通过注解声明事务边界,由 Spring AOP 自动处理 commit/rollback。
- 方法正常结束 → Spring 自动 commit
- 方法抛出未捕获的 RuntimeException 或 Error → Spring 自动 rollback
- 想让受检异常也触发回滚 → 必须加
rollbackFor参数,例如:@Transactional(rollbackFor = IOException.class)或@Transactional(rollbackFor = {IOException.class, SQLException.class}) - 方法必须是 public,且由 Spring 容器代理调用(不能 new 实例直接调用)
- 异常不能被方法内部 try-catch 吞掉——如果 catch 了但没 re-throw,事务切面看不到异常,就不会 rollback
手动 JDBC 事务:用 Connection.rollback()
绕过框架、直连数据库时,需自己控制事务生命周期:
- 先调用
connection.setAutoCommit(false)关闭自动提交 - 执行多条 SQL 操作(insert/update/delete)
- 若全部成功,调用
connection.commit() - 若发生异常,在 catch 块中调用
connection.rollback() - finally 中务必恢复 auto-commit 状态或关闭连接,避免连接泄漏或静默失败
编程式事务:TransactionTemplate 或 TransactionStatus
适合需要动态控制事务(如条件判断是否开启、嵌套分支处理)的场景:
立即学习“Java免费学习笔记(深入)”;
- 注入
TransactionTemplate,用execute()执行业务逻辑 - 在回调中,可主动调用
status.setRollbackOnly()标记当前事务仅回滚 - 也可在 catch 块中显式调用
transactionManager.rollback(status) - 比声明式更灵活,但代码侵入性强,一般只在必要时使用
多线程环境下事务回滚的注意事项
事务是**与线程绑定**的,Spring 默认事务上下文不跨线程传递:
- 主线程开启事务后,新起子线程(Thread / ExecutorService.submit)无法继承该事务
- 子线程内抛异常,只会回滚它自己的数据库连接(如果有的话),不影响主线程事务
- 如需协同回滚,常见做法是:主线程用
Future.get()阻塞等待子线程结果;子线程异常时主线程捕获并主动标记setRollbackOnly()或抛出运行时异常 - 不建议在子线程中操作主线程的事务资源,容易导致状态混乱或连接泄漏


















