Spring Boot的@Transactional注解是否真的开启事务?多操作回滚失败怎么办
问题原因
- 异常回滚规则不匹配:Spring声明式事务默认仅对
RuntimeException和Error类型的异常触发回滚,你代码中抛出的ConfigurationException如果是继承自Exception的受检异常,默认不会触发事务回滚,会直接提交之前已经执行成功的数据库操作。 - 内部方法事务传播属性配置错误:如果
EnteteService.save、DetailService.saveAllDetails等内部调用的方法自身也加了@Transactional注解,且传播属性设置为REQUIRES_NEW,会为每个方法开启独立事务,方法执行完就单独提交,不受外层事务回滚影响。 @Transactional未生效:如果configure方法不是public修饰,或者方法所在类没有被Spring托管(未添加@Service/@Component等注解)、调用configure时使用的是自行new的对象而非Spring注入的代理对象,都会导致事务注解失效,每个数据库操作会开启独立事务单独提交。- 多数据源场景:如果你的JPA和JdbcTemplate分别绑定了不同的数据源,默认的单数据源事务无法跨数据源管控操作,每个数据源的操作会单独提交。
解决方案
- 调整事务回滚规则,修改
@Transactional注解指定所有异常都触发回滚:
@Transactional(rollbackFor = Exception.class)
- 检查内部业务方法的事务传播属性,将不需要独立事务的方法的传播属性设置为默认的
REQUIRED(不加传播属性配置即为默认值),不要使用REQUIRES_NEW,保证所有操作都加入外层的configure事务统一提交/回滚。 - 保证
configure方法为public修饰,所在类添加Spring服务注解,且调用configure方法时使用Spring注入的实例,不要用类内部this调用或者自行创建的类实例。 - 如果是多数据源场景,统一JPA和JdbcTemplate的数据源配置,让二者使用同一个数据库连接池,单数据源事务即可管控所有操作;如果确实需要多数据源,需要集成JTA或者Seata等分布式事务组件实现跨数据源的事务管控。
内容的提问来源于stack exchange,提问作者Khaled
相关产品推荐
相关产品推荐

