Java中级项目中异常回滚依赖事务机制自动完成,需满足三要素:异常传播出去、事务配置正确、数据源支持事务;@Transactional仅对public方法生效,且必须由Spring代理调用,只对RuntimeException和Error默认回滚,受检异常需显式指定rollbackFor,数据库须用InnoDB等支持事务的引擎,非DB操作需手动补偿。

Java中级项目中,异常回滚不是靠“手动写代码撤回操作”,而是依赖事务管理机制自动完成的——关键在于让异常真正传播出去、事务配置正确、数据源支持事务。
事务方法必须是public且由Spring代理调用
Spring的声明式事务(@Transactional)基于AOP代理实现。如果方法是private、protected、或在同一个类里直接调用(this.method()),事务注解不会生效,异常发生时也不会回滚。
- 确保被@Transactional标注的方法是public的
- 避免在本类中用this调用事务方法,应通过注入自身Bean或重构为跨Service协作
- 检查是否启用了@EnableTransactionManagement(Spring Boot默认开启)
只对运行时异常(RuntimeException)和Error默认回滚
@Transactional默认只在遇到未捕获的RuntimeException及其子类、或Error时触发回滚。如果catch了异常又没重新抛出,或者抛出的是Exception(如IOException、SQLException),事务将正常提交。
- 需要对特定受检异常回滚:@Transactional(rollbackFor = IOException.class)
- 明确不希望某异常导致回滚:@Transactional(noRollbackFor = BusinessException.class)
- 不要在事务方法内静默吞掉异常(空catch或只打日志)
数据库操作必须走支持事务的JDBC连接
即使代码写了@Transactional,若底层数据源不支持事务(如H2内存模式配成non-transactional)、或用了JdbcTemplate但未绑定到事务连接、或混用了JPA/Hibernate与原生JDBC却没共用同一DataSource,回滚也会失效。
立即学习“Java免费学习笔记(深入)”;
- 确认使用的DataSource是Spring管理的(如HikariCP),且数据库引擎支持事务(MySQL用InnoDB,别用MyISAM)
- 避免在事务方法中使用new JdbcTemplate(new DriverManagerDataSource(...))——这会脱离事务上下文
- 多数据源场景下,@Transactional(value = "xxxTransactionManager")要指定正确的事务管理器
非数据库操作无法自动回滚,需手动补偿
发邮件、写文件、调用第三方HTTP接口等操作不在数据库事务范围内。一旦这些操作成功而后续DB操作失败,就会出现数据不一致。
- 把外部调用尽量后置——先完成所有DB变更,再做通知类操作
- 必须前置时,记录操作日志(如消息表+状态字段),配合定时任务做最终一致性补偿
- 强一致性要求高时,考虑Saga模式或本地消息表+可靠消息队列
事务不是万能开关,它只管住你交给它的那一段数据库操作。回滚能否生效,取决于异常有没有逃出事务边界、容器有没有真正接管、底层有没有能力回退——三者缺一不可。










