标准答案
- 确认对象由 Spring 容器创建,调用经过代理,方法可被代理机制拦截。
- 确认异常是否从事务边界抛出,以及 checked exception 是否配置了回滚规则。
- 确认数据库连接、数据源和事务管理器一致,SQL 确实在同一事务连接中执行。
- 通过日志、事务同步回调、数据库观察和最小复现验证,而不是只看注解是否存在。
题目解析
先确认调用对象是否由容器创建且经过代理,再确认异常是否从事务边界抛出,最后确认 SQL 使用了正确数据源和同一事务连接。注解存在不代表运行时边界成立。
异常被 catch 后不再抛出、checked exception 不在回滚规则中、事务已经提交或内部自调用,都会让“看起来应该回滚”的代码产生不同结果。
多数据源场景要明确事务管理器和数据源绑定,必要时用最小复现插入可观察记录,结合事务日志和数据库结果验证,而不是只看日志里打印了事务注解。
常见误区
- 误区:catch 后不重新抛出却期待回滚。改正:配置回滚规则或重新抛出能触发回滚的异常,并验证业务状态。
- 误区:用方法内部自调用测试事务。改正:通过代理 Bean 的外部调用进入事务,或调整服务边界。
- 误区:多个数据源却使用错误事务管理器。改正:显式绑定数据源、事务管理器和 mapper,使用提交后数据验证。