MyBatis SqlSession 与缓存机制实例详解

 更新时间:2026年06月01日 10:06:41   作者:骄马之死  
Spring整合MyBatis中的SqlSession管理机制与缓存策略,详细解析了SqlSession绑定线程、事务的原理,以及一级、二级缓存的工作机制与配置方法,感兴趣的朋友跟随小编一起看看吧

一、Spring 管理下的 SqlSession 核心机制

Spring 会将 SqlSession当前线程事务进行强绑定,这是 MyBatis 整合 Spring 后最核心的运行机制,保证了事务一致性与线程安全。

1. 完整生命周期流程

  • 事务开启阶段
    • Spring 会检查当前线程是否已绑定 SqlSession,若不存在,则创建 SqlSession 并绑定到 ThreadLocal 中,实现线程隔离。
  • SQL 执行阶段
    • 所有 Mapper 接口都会通过当前线程绑定的 SqlSession 访问数据库,保证同一事务内使用同一个连接和会话。
  • 事务/请求结束阶段
    • Spring 事务管理器自动触发 closeSqlSession 逻辑
    • 清空 MyBatis 一级缓存
    • 释放数据库连接(Connection)并归还连接池
    • 解除绑定:将 SqlSession 从当前线程的 ThreadLocal 中移除

2. Mapper 调用底层原理(以userMapper.selectById(1)为例)

Mapper 接口本身没有实现类,底层是 JDK 动态代理对象,所有调用最终都会交给 SqlSession 执行。

核心代码示意

// 1. 获取 SqlSession
SqlSession session = sqlSessionFactory.openSession();
// 2. 通过 SqlSession 创建 Mapper 代理对象
UserMapper mapper = session.getMapper(UserMapper.class);
// 3. 本质:调用 SqlSession 的 selectOne 等方法
mapper.selectById(1);

3. Spring 整合后的详细执行流程

第一步:事务前置准备

Spring 事务拦截器 TransactionInterceptor 优先执行:

  1. 通过事务管理器 PlatformTransactionManager 获取数据库连接
  2. 将连接存入 TransactionSynchronizationManager(底层基于 ThreadLocal)
  3. 注意:此阶段仅准备数据库连接,SqlSession 尚未创建

第二步:执行 Mapper 方法(SqlSession 创建时机)

当代码执行到 userMapper.selectById(1) 时:

  1. 进入 Mapper 动态代理对象,调用 SqlSessionTemplate
  2. SqlSessionTemplate 委托 SqlSessionUtils 获取当前会话
  3. 复用/创建规则
    • 线程已有 SqlSession → 直接复用
    • 无线程会话 → 创建新 SqlSession,并绑定到当前 Spring 事务上下文

4. 非事务环境的问题

如果未开启 Spring 事务,执行逻辑会发生变化:

  • 每执行一个 Mapper 方法,Spring 都会创建一个临时 SqlSession
  • 方法执行完毕后立即关闭会话
  • 后果:一级缓存完全失效,多次相同查询会重复访问数据库,性能下降,且无法保证查询结果的数据一致性

二、MyBatis 一级缓存

核心定义

一级缓存是 SqlSession 级别的缓存,属于默认开启、无法关闭的本地缓存。

工作机制

同一个 SqlSession 内,执行完全相同的 SQL、参数时:

  1. 第一次查询 → 访问数据库,并将结果存入一级缓存
  2. 后续相同查询 → 直接从内存读取,不再请求数据库
  3. 会话提交/关闭/执行增删改操作 → 缓存自动清空

适用场景

单次请求、单次事务内的重复查询优化。

三、MyBatis 二级缓存

核心定义

二级缓存是 Mapper(Namespace)级别的缓存,跨 SqlSession 共享,多个线程/会话可以访问同一份缓存数据。

工作机制

  1. 当 SqlSession 提交或关闭时,会将一级缓存的数据同步到二级缓存
  2. 其他 SqlSession 执行相同 Mapper 的相同查询时,优先查询二级缓存
  3. 执行增删改操作 → 该 Namespace 下的二级缓存自动清空

开启方式

  • 全局配置(默认已开启)
  • mybatis-config.xml 中启用缓存开关:
  • <setting name="cacheEnabled" value="true"/>
  • Mapper 配置
  • 在对应的 Mapper.xml 文件中添加缓存标签:
  • <cache/>
  • 实体类要求
  • 缓存的 POJO 实体类必须实现 Serializable 序列化接口(二级缓存支持持久化到磁盘、Redis 等存储介质)。

总结

  1. SqlSession:由 Spring 托管,与线程、事务绑定,保证同一事务内会话唯一,非事务环境会导致会话频繁创建销毁、一级缓存失效。
  2. 一级缓存:SqlSession 级别,默认开启,会话内共享,会话关闭即清空。
  3. 二级缓存:Mapper 级别,跨会话共享,需手动开启,支持分布式/持久化存储,适用于读多写少的场景。

到此这篇关于MyBatis SqlSession 与缓存机制详解的文章就介绍到这了,更多相关MyBatis SqlSession 缓存内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java线程池的拒绝策略实现详解

    Java线程池的拒绝策略实现详解

    这篇文章主要介绍了Java线程池的拒绝策略实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • 基于maven中多个子模块的构建顺序

    基于maven中多个子模块的构建顺序

    这篇文章主要介绍了maven中多个子模块的构建顺序,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • spring boot整合mybatis+mybatis-plus的示例代码

    spring boot整合mybatis+mybatis-plus的示例代码

    这篇文章主要介绍了spring boot整合mybatis+mybatis-plus的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • SpringBoot2.动态@Value的实现方式

    SpringBoot2.动态@Value的实现方式

    这篇文章主要介绍了SpringBoot2.动态@Value的实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Java多线程中的Interrupt简析

    Java多线程中的Interrupt简析

    这篇文章主要介绍了Java多线程中的Interrupt简析,Interrupt 的其作用是"中断"线程, 但实际上线程仍会继续运行, 这是一个非常容易混淆的概念,Interrupt 的真正作用是给线程对象设置一个中断标记, 并不会影响线程的正常运行,需要的朋友可以参考下
    2023-09-09
  • 详解Java的设计模式编程中的原型模式

    详解Java的设计模式编程中的原型模式

    这篇文章主要介绍了Java的设计模式编程中的原型模式,处理对象复制时要特别注意浅拷贝和深拷贝的问题,需要的朋友可以参考下
    2016-02-02
  • SpringCloud整合Nacos实现流程详解

    SpringCloud整合Nacos实现流程详解

    这篇文章主要介绍了SpringCloud整合Nacos实现流程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • springboot项目用maven插件打包时报错的解决方法

    springboot项目用maven插件打包时报错的解决方法

    文章介绍了解决Spring Boot项目使用Maven插件打包时遇到JDK版本无效问题的步骤,本文分步骤给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2026-01-01
  • Spring中的BeanFactory与FactoryBean区别详解

    Spring中的BeanFactory与FactoryBean区别详解

    这篇文章主要介绍了Spring中的BeanFactory与FactoryBean区别详解,BeanFactory是一个接口,它是spring中的一个工厂,FactoryBean也是一个接口,实现了3个方法,通过重写其中方法自定义生成bean,需要的朋友可以参考下
    2024-01-01
  • java中Websocket的使用方法例子

    java中Websocket的使用方法例子

    这篇文章主要给大家介绍了关于java中Websocket的使用方法,WebSocket是HTML5开始提供的一种在浏览器和服务器间进行全双工通信的协议,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-11-11

最新评论