在 Java + MyBatis 项目中,“事务失效”是一个非常常见的问题,通常不是 MyBatis 本身的问题,而是 Spring 事务机制 + 使用方式 导致的。下面按最常见原因 → 原理 → 解决方案给你系统梳理。
public原因:
Spring 的 @Transactional 只对 public 方法生效。
@Transactional
void insert() { // ❌ 私有/包级方法无效
}
✅ 解决:
@Transactional
public void insert() {
}
@Service
public class UserService {
public void a() {
b(); // ❌ 事务失效
}
@Transactional
public void b() {
// 数据库操作
}
}
原因:
Spring 事务是通过 AOP 代理 实现的,自调用不会走代理。
✅ 解决方式:
@Service
public class UserService {
@Autowired
private UserInnerService inner;
public void a() {
inner.b();
}
}
@Service
public class UserInnerService {
@Transactional
public void b() {}
}
@Autowired
private UserService self;
public void a() {
self.b();
}
@Transactional
public void test() {
try {
dao.insert();
} catch (Exception e) {
// ❌ 吞掉异常
}
}
原因:
Spring 默认只在 RuntimeException / Error 时回滚。
✅ 解决:
throw new RuntimeException(e);
或手动回滚:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
默认回滚:
RuntimeExceptionError不回滚:
Exception(受检异常)@Transactional
public void test() throws Exception {
throw new Exception("xx"); // ❌ 不回滚
}
✅ 解决:
@Transactional(rollbackFor = Exception.class)
常见错误:
DataSourceTransactionManager✅ 正确配置示例:
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
多数据源:
@Transactional(transactionManager = "orderTxManager")
❌ 错误方式:
SqlSession session = sqlSessionFactory.openSession();
✅ 正确方式:
Mapper 接口@Autowired
private UserMapper userMapper;
| 检查项 | 是否正确 |
|---|---|
| 方法是 public | ✅ |
| 不是同类自调用 | ✅ |
| 异常有抛出 | ✅ |
| 有事务管理器 | ✅ |
| Mapper 由 Spring 管理 | ✅ |
| 单数据源或指定 txManager | ✅ |
MyBatis 事务失效,99% 是 Spring 事务没生效,不是 MyBatis 的问题。
如果你愿意,可以把你的 代码 / 配置(@Transactional、数据源、调用方式) 贴出来,我可以直接帮你定位是哪一条原因。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。