事务未回滚主因是配置失效而非未配置,需排查异常是否穿透代理、回滚规则是否匹配、事务上下文是否存在及能否手动标记回滚。

事务未回滚不是“没配置”,而是“配置了但没起作用”。排查关键在于确认:异常是否被 Spring 事务切面捕获到、事务上下文是否有效、回滚条件是否匹配。下面从四个高频隐患切入,直击问题本质。
看异常是否被代理真正捕获
Spring 事务靠 AOP 代理在方法边界织入回滚逻辑,前提是异常必须“穿透代理”——即不能被本方法吞掉,也不能绕过代理调用。
- 方法内用了 try-catch 且未 re-throw:比如 catch 后只 log + return,事务会当作正常流程提交
- 发生内部调用(self-invocation):如 service 中 methodA() 直接调用 this.methodB(),绕过代理,@Transactional 失效
- 方法是 private / final / static:JDK 或 CGLIB 代理无法增强,注解被忽略
验证方式:开启 DEBUG 日志 logging.level.org.springframework.transaction=DEBUG,触发异常后搜索日志中是否有 “Completing transaction for … after exception”;若无,大概率是代理未介入。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
查回滚规则是否匹配异常类型
默认只对 RuntimeException 及其子类、Error 自动回滚。抛出 IOException、SQLException、自定义 Exception 等受检异常时,事务静默提交。
- 检查 @Transactional 是否漏配 rollbackFor,例如应写
@Transactional(rollbackFor = Exception.class)而非空注解 - 警惕 noRollbackFor 误配:比如写了
@Transactional(noRollbackFor = BusinessException.class),但该异常本该回滚 - 避免业务异常错误继承 Error:如
class BizError extends Error—— 语义错位,破坏分层,且可能因 JVM 对 Error 的特殊处理导致代理中断
验事务上下文是否真实存在
事务不是“加了注解就一定有”,它依赖完整的运行时环境。
- 数据源引擎不支持事务:MySQL 表引擎为 MyISAM 时,即使 Spring 开启事务也无效(InnoDB 才支持)
- 异步线程或定时任务中使用 @Transactional:事务上下文不传递,@Transactional 完全失效
- 未被 Spring 容器管理的对象:new 出来的 service 实例,没有代理,注解无意义
-
事务传播行为冲突:比如外层方法用
PROPAGATION_NOT_SUPPORTED,内层事务会被挂起甚至丢弃
试手动干预能否触发回滚
当业务要求“不抛异常但必须回滚”(如校验失败需撤回已执行操作),可主动标记:
- 在 catch 块或判断分支中调用:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly() - 使用前建议加保护:
if (TransactionSynchronizationManager.isActualTransactionActive()) { ... },避免 NPE - 注意:该操作仅标记回滚,不终止方法执行,后续代码仍会运行
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










