You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring整合MyBatis时,两次数据库操作事务回滚失效问题求助

Spring+MyBatis事务不回滚问题排查与解决

看起来你遇到的核心问题是Spring事务默认不会对Checked Exception触发回滚,而你碰到的MySQLIntegrityConstraintViolationException恰好属于Checked Exception范畴,这就导致插入失败时删除操作没有被回滚。

问题原因分析

Spring的@Transactional注解默认回滚规则是:仅当抛出RuntimeException或Error时,才会触发事务回滚。而MySQLIntegrityConstraintViolationException继承自SQLException,属于Checked Exception,不在默认回滚的范围内。你的方法addRecord()声明抛出Exception,异常抛出后Spring事务管理器不会自动执行回滚逻辑。

解决方案

你需要显式通过@Transactional的rollbackFor属性指定需要触发回滚的异常类型,有两种常用方式:

1. 针对具体异常(推荐,更精准)

修改方法上的@Transactional注解,指定仅对MySQLIntegrityConstraintViolationException回滚:

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = MySQLIntegrityConstraintViolationException.class)
public boolean addRecord() throws Exception {
    myMapper.deleteRecord(id);
    myMapper.insertRecord(- - -);
    return true;
}

2. 针对所有Exception(适用于需要对所有异常回滚的场景)

如果希望任何Exception类型都触发回滚,可以直接指定rollbackFor = Exception.class:

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public boolean addRecord() throws Exception {
    myMapper.deleteRecord(id);
    myMapper.insertRecord(- - -);
    return true;
}

额外验证点

除了修改注解,还要确认以下几点确保事务正常工作:

  • 方法内部没有捕获并吞掉MySQLIntegrityConstraintViolationException,必须让异常抛出到Spring事务代理层,事务管理器才能感知并触发回滚。
  • 确保SqlSessionFactoryBean使用的数据源和transactionManager()中的dataSource()是同一个实例,可在sqlSessionFactoryBean()方法中添加sessionFactory.setDataSource(dataSource());来明确绑定。
  • 确认@EnableTransactionManagement配置生效,你的配置中已经设置proxyTargetClass = true,且MyService被@Service注解标记,属于Spring容器管理的Bean,这部分是没问题的。

从你提供的日志来看,事务已经成功同步了SqlSession,但因为异常类型不在默认回滚范围内,所以没有执行回滚。修改rollbackFor属性后,插入失败时删除操作应该就能正常回滚了。

内容的提问来源于stack exchange,提问作者Pankaj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:41:23