MyBatis SqlSession 与缓存机制实例详解
作者:骄马之死
Spring整合MyBatis中的SqlSession管理机制与缓存策略,详细解析了SqlSession绑定线程、事务的原理,以及一级、二级缓存的工作机制与配置方法,感兴趣的朋友跟随小编一起看看吧
一、Spring 管理下的 SqlSession 核心机制
Spring 会将 SqlSession 与当前线程、事务进行强绑定,这是 MyBatis 整合 Spring 后最核心的运行机制,保证了事务一致性与线程安全。
1. 完整生命周期流程
- 事务开启阶段
- Spring 会检查当前线程是否已绑定 SqlSession,若不存在,则创建 SqlSession 并绑定到
ThreadLocal中,实现线程隔离。
- Spring 会检查当前线程是否已绑定 SqlSession,若不存在,则创建 SqlSession 并绑定到
- SQL 执行阶段
- 所有 Mapper 接口都会通过当前线程绑定的 SqlSession 访问数据库,保证同一事务内使用同一个连接和会话。
- 事务/请求结束阶段
- Spring 事务管理器自动触发
closeSqlSession逻辑 - 清空 MyBatis 一级缓存
- 释放数据库连接(Connection)并归还连接池
- 解除绑定:将 SqlSession 从当前线程的 ThreadLocal 中移除
- Spring 事务管理器自动触发
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 优先执行:
- 通过事务管理器
PlatformTransactionManager获取数据库连接 - 将连接存入
TransactionSynchronizationManager(底层基于 ThreadLocal) - 注意:此阶段仅准备数据库连接,SqlSession 尚未创建
第二步:执行 Mapper 方法(SqlSession 创建时机)
当代码执行到 userMapper.selectById(1) 时:
- 进入 Mapper 动态代理对象,调用
SqlSessionTemplate SqlSessionTemplate委托SqlSessionUtils获取当前会话- 复用/创建规则
- 线程已有 SqlSession → 直接复用
- 无线程会话 → 创建新 SqlSession,并绑定到当前 Spring 事务上下文
4. 非事务环境的问题
如果未开启 Spring 事务,执行逻辑会发生变化:
- 每执行一个 Mapper 方法,Spring 都会创建一个临时 SqlSession
- 方法执行完毕后立即关闭会话
- 后果:一级缓存完全失效,多次相同查询会重复访问数据库,性能下降,且无法保证查询结果的数据一致性
二、MyBatis 一级缓存
核心定义
一级缓存是 SqlSession 级别的缓存,属于默认开启、无法关闭的本地缓存。
工作机制
在同一个 SqlSession 内,执行完全相同的 SQL、参数时:
- 第一次查询 → 访问数据库,并将结果存入一级缓存
- 后续相同查询 → 直接从内存读取,不再请求数据库
- 会话提交/关闭/执行增删改操作 → 缓存自动清空
适用场景
单次请求、单次事务内的重复查询优化。
三、MyBatis 二级缓存
核心定义
二级缓存是 Mapper(Namespace)级别的缓存,跨 SqlSession 共享,多个线程/会话可以访问同一份缓存数据。
工作机制
- 当 SqlSession 提交或关闭时,会将一级缓存的数据同步到二级缓存
- 其他 SqlSession 执行相同 Mapper 的相同查询时,优先查询二级缓存
- 执行增删改操作 → 该 Namespace 下的二级缓存自动清空
开启方式
- 全局配置(默认已开启)
- 在
mybatis-config.xml中启用缓存开关: <setting name="cacheEnabled" value="true"/>
- Mapper 配置
- 在对应的
Mapper.xml文件中添加缓存标签: <cache/>
- 实体类要求
- 缓存的 POJO 实体类必须实现
Serializable序列化接口(二级缓存支持持久化到磁盘、Redis 等存储介质)。
总结
- SqlSession:由 Spring 托管,与线程、事务绑定,保证同一事务内会话唯一,非事务环境会导致会话频繁创建销毁、一级缓存失效。
- 一级缓存:SqlSession 级别,默认开启,会话内共享,会话关闭即清空。
- 二级缓存:Mapper 级别,跨会话共享,需手动开启,支持分布式/持久化存储,适用于读多写少的场景。
到此这篇关于MyBatis SqlSession 与缓存机制详解的文章就介绍到这了,更多相关MyBatis SqlSession 缓存内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
您可能感兴趣的文章:
- Mybatis的SqlSession和一级缓存的失效原因分析及解决
- MyBatis SqlSession执行流程小结
- springboot3集成mybatis-plus报sqlSession异常的问题解决
- MyBatis的通俗理解:SqlSession.getMapper()源码解读
- 详解Mybatis核心类SqlSessionFactory的构建
- SpringBoot3整合MyBatis出现异常:Property 'sqlSessionFactory'or 'sqlSessionTemplate' are required
- Mybatis SqlSessionFactory与SqlSession详细讲解
- 使用Mybatis-Plus时的SqlSessionFactory问题及处理
