当前位置: 代码网 > it编程>编程语言>Java > 在Spring Boot中MyBatis 的自动提交行为全解析(最新整理)

在Spring Boot中MyBatis 的自动提交行为全解析(最新整理)

2026年01月23日 Java 我要评论
在 spring boot 中,mybatis 的“自动提交”行为并不是 mybatis 自己实现的,而是 由 spring 框架通过事务管理器(platformtransac

在 spring boot 中,mybatis 的“自动提交”行为并不是 mybatis 自己实现的,而是 由 spring 框架通过事务管理器(platformtransactionmanager)统一控制的。mybatis 原生默认是 不自动提交(autocommit=false),但在 spring boot 集成环境下,是否提交由 spring 的事务传播机制决定:

一、核心结论

场景是否自动提交?控制者
原生 mybatis(无 spring)❌ 默认不提交,需手动 sqlsession.commit()mybatis 自身
spring boot + mybatis(无 @transactional✅ 自动提交(每条 sql 独立事务)spring 的 datasourcetransactionmanager
spring boot + mybatis(有 @transactional❌ 方法结束前不提交,成功则提交,异常则回滚spring 事务管理

✅ 所以你看到的“自动提交”,其实是 spring 在方法无事务注解时,为每个数据库操作开启并立即提交一个独立事务

二、spring boot 如何集成 mybatis?

spring boot 通过 mybatis-spring-boot-starter 自动配置:

  • 创建 sqlsessionfactory
  • 创建 sqlsessiontemplate(线程安全的 sqlsession 代理)
  • 注册 mapper 接口为 spring bean

关键点:不再直接使用原生 sqlsession,而是通过 sqlsessiontemplate 代理调用。

三、源码分析:为什么“自动提交”?

1.sqlsessiontemplate的代理机制

sqlsessiontemplate 是 mybatis-spring 提供的线程安全 sqlsession 实现,它内部持有一个 sqlsessioninterceptor(动态代理)。

当调用 mapper 方法(如 usermapper.insert(user))时,实际执行路径:

mapper proxy → sqlsessiontemplate → sqlsessioninterceptor.invoke()

查看 sqlsessioninterceptor.invoke() 源码(简化版):

public object invoke(object proxy, method method, object[] args) throws throwable {
    // 1. 获取当前 spring 管理的 sqlsession(可能已存在事务上下文)
    sqlsession sqlsession = getsqlsession(
        sqlsessiontemplate.this.sqlsessionfactory,
        sqlsessiontemplate.this.executortype,
        sqlsessiontemplate.this.exceptiontranslator
    );
    try {
        // 2. 执行 sql(如 insert/update/delete/select)
        object result = method.invoke(sqlsession, args);
        // 3. 如果当前没有 spring 事务,则立即 commit(仅对更新操作)
        if (!issqlsessiontransactional(sqlsession, sqlsessiontemplate.this.sqlsessionfactory)) {
            sqlsession.commit(true); // true 表示强制提交
        }
        return result;
    } catch (throwable t) {
        // 异常处理...
        throw t;
    } finally {
        // 4. 如果不是 spring 事务管理的 sqlsession,则关闭它
        if (!issqlsessiontransactional(sqlsession, sqlsessiontemplate.this.sqlsessionfactory)) {
            sqlsession.close();
        }
    }
}

🔍 关键判断:issqlsessiontransactional(...)

  • 如果当前线程 已有 spring 事务(即处于 @transactional 方法中),则返回 true不提交、不关闭,交由 spring 统一管理。
  • 如果 没有 spring 事务,则返回 false立即提交并关闭 sqlsession

这就解释了“自动提交”的来源!

2.issqlsessiontransactional的实现逻辑

该方法检查当前 sqlsession 是否被 spring 事务管理:

// org.mybatis.spring.sqlsessionutils
public static boolean issqlsessiontransactional(sqlsession session, sqlsessionfactory sessionfactory) {
    // 从 threadlocal 中获取 spring 管理的 sqlsession
    sqlsessionholder holder = (sqlsessionholder) transactionsynchronizationmanager
        .getresource(sessionfactory);
    return (holder != null) && (holder.getsqlsession() == session);
}
  • transactionsynchronizationmanager.getresource() 是 spring 事务同步的核心机制。
  • 只有在 @transactional 方法中,spring 才会提前将 sqlsession 绑定到 threadlocal
  • 否则,holder == null,返回 false → 触发自动提交。

3. spring 事务如何接管 sqlsession?

当方法标注 @transactional 时,spring 会:

  1. 在方法开始前,通过 datasourcetransactionmanager 开启 jdbc 事务(connection.setautocommit(false))。
  2. 调用 sqlsessionutils.getsqlsession() 时,发现已有事务,复用同一个 connection,并将其包装为 sqlsession 存入 threadlocal
  3. 方法结束时,根据是否抛异常,调用 commit() 或 rollback()
  4. 最终由 spring 负责 close()

此时,sqlsessiontemplate 不会干预提交行为。

四、验证实验

场景 1:无@transactional

@service
public class userservice {
    @autowired
    private usermapper usermapper;
    public void saveuser(user user) {
        usermapper.insert(user); // 自动提交!
    }
}

✅ 插入成功,即使后续代码抛异常,数据也不会回滚。

场景 2:有@transactional

@transactional
public void saveuserwithtx(user user) {
    usermapper.insert(user);
    throw new runtimeexception("模拟异常"); // 数据会回滚!
}

❌ 插入被回滚,因为整个方法是一个事务。

五、配置项说明

虽然 mybatis 有 autocommit 配置,但在 spring boot 中 几乎无效,因为:

  • spring 通过 datasource 获取 connection,并由事务管理器控制 setautocommit()
  • mybatis 的 autocommit 参数在 sqlsessionfactorybean 中会被忽略(或覆盖)。

所以,不要依赖 mybatis 的 autocommit,而应使用 spring 的 @transactional

六、总结

问题答案
spring boot 中 mybatis 为何“自动提交”?因为 spring 在无事务方法中,为每次 mapper 调用创建独立事务并立即提交。
源码关键类sqlsessiontemplate.sqlsessioninterceptor + sqlsessionutils
控制提交行为的方式使用 @transactional 注解,而非 mybatis 配置
是否应关闭“自动提交”?不需要关闭,这是 spring 的合理默认行为;需事务时加 @transactional 即可

💡 最佳实践

  • 简单查询/单条写入:无需 @transactional,享受自动提交。
  • 多操作一致性要求:必须加 @transactional
  • 永远不要在 service 层手动调用 sqlsession.commit()

通过 spring 的声明式事务,开发者既能获得“自动提交”的便利,又能灵活控制复杂事务,这正是 spring boot + mybatis 的强大之处。

到此这篇关于在spring boot中mybatis 的自动提交行为全解析(最新整理)的文章就介绍到这了,更多相关spring boot mybatis 自动提交内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com