Spring @Transactional事务执行删插操作出现意外回滚问题求助
问题根因
- 事务传播行为冲突
Spring@Transactional默认传播级别为Propagation.REQUIRED,即当前存在事务时直接加入已有事务。你在业务层exampleFunction开启了外层事务,Repo层两个方法的@Transactional会直接加入该外层事务。如果Repo层方法执行抛出异常,哪怕你在上层catch了异常,事务管理器已经将当前全局事务标记为「仅回滚」,等外层事务尝试提交时,就会触发Unexpected Rollback异常。 - 异常处理逻辑缺失
你在exampleFunction中仅捕获了异常打印日志,没有主动处理事务回滚标记,事务管理器在方法结束时默认尝试提交已被标记为回滚的事务,最终抛出异常。
解决方案
方案1(推荐,符合你的业务需求):统一用外层事务管控所有操作
删除Repo层deleteall、insertall方法上的@Transactional注解,仅保留exampleFunction上的事务注解,所有数据库操作绑定到同一个全局事务,任意步骤失败都会触发整体回滚。
如果需要保留异常捕获逻辑,需手动标记事务回滚:
@Transactional(rollbackFor = Exception.class) exampleFunction(...){ try { repo.deleteall(...); repo.insertall(...); } catch (Exception e) { System.out.println("exception"); // 手动标记当前事务回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } }
注:添加
rollbackFor = Exception.class是为了让受检异常也能触发回滚,适配Spring默认仅对RuntimeException、Error回滚的逻辑。
方案2(仅适用于需要Repo方法事务独立的场景):调整传播级别
如果确实需要Repo层方法的事务完全独立,将Repo层两个方法的事务传播级别改为Propagation.REQUIRES_NEW,每个Repo方法会开启独立的新事务,异常不会影响外层事务的提交状态。但该方案不符合你「插入失败回滚删除操作」的需求,不推荐使用。
额外排查点
- 确认你使用的
@Transactional是Spring包下的org.springframework.transaction.annotation.Transactional,而非JPA的javax.transaction.Transactional。 - 确认业务代码中没有其他切面提前捕获了异常修改了事务状态。
内容的提问来源于stack exchange,提问作者Raghav
相关产品推荐
相关产品推荐

