温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java mybatis为何事务失效

发布时间:2026-09-23 05:43:33 来源:亿速云 阅读:96 作者:小樊 栏目:编程语言

在 Java + MyBatis 项目中,“事务失效”是一个非常常见的问题,通常不是 MyBatis 本身的问题,而是 Spring 事务机制 + 使用方式 导致的。下面按最常见原因 → 原理 → 解决方案给你系统梳理。


一、最常见原因总结(先记住这 6 条)

  1. 方法不是 public
  2. 同类方法内部调用(自调用)
  3. 异常被 catch 吃掉
  4. 抛出的异常类型不对
  5. 没有配置事务管理器 / 多数据源
  6. MyBatis 使用了非 Spring 管理的数据源

二、详细原因与解决方案

1️⃣ 方法不是 public

原因:
Spring 的 @Transactional 只对 public 方法生效。

@Transactional
void insert() {  // ❌ 私有/包级方法无效
}

✅ 解决:

@Transactional
public void insert() {
}

2️⃣ 同类内部方法调用(最坑)

@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();
}

3️⃣ 异常被 catch 了

@Transactional
public void test() {
    try {
        dao.insert();
    } catch (Exception e) {
        // ❌ 吞掉异常
    }
}

原因:
Spring 默认只在 RuntimeException / Error 时回滚。

✅ 解决:

throw new RuntimeException(e);

或手动回滚:

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

4️⃣ 抛出的异常类型不对

默认回滚:

  • RuntimeException
  • Error

不回滚:

  • Exception(受检异常)
@Transactional
public void test() throws Exception {
    throw new Exception("xx"); // ❌ 不回滚
}

✅ 解决:

@Transactional(rollbackFor = Exception.class)

5️⃣ 没有事务管理器 / 多数据源问题

常见错误:

  • 只引入了 MyBatis,没配置 DataSourceTransactionManager
  • 多数据源但没指定事务管理器

✅ 正确配置示例:

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}

多数据源:

@Transactional(transactionManager = "orderTxManager")

6️⃣ MyBatis 使用了“自己 new 的 SqlSession”

❌ 错误方式:

SqlSession session = sqlSessionFactory.openSession();

✅ 正确方式:

  • 使用 Mapper 接口
  • 交给 Spring 管理
@Autowired
private UserMapper userMapper;

三、MyBatis 事务失效自查清单 ✅

检查项 是否正确
方法是 public ✅
不是同类自调用 ✅
异常有抛出 ✅
有事务管理器 ✅
Mapper 由 Spring 管理 ✅
单数据源或指定 txManager ✅

四、一句话总结

MyBatis 事务失效,99% 是 Spring 事务没生效,不是 MyBatis 的问题。

如果你愿意,可以把你的 代码 / 配置(@Transactional、数据源、调用方式) 贴出来,我可以直接帮你定位是哪一条原因。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI
助
手