在数据库访问层,缓存是提升性能、降低数据库负载的利器。MyBatis提供了一级缓存和二级缓存两套机制,但许多开发者对其工作原理、作用域和失效条件混淆不清,常导致数据不一致或缓存命中率低下等问题。透彻理解MyBatis一级缓存与二级缓存原理区别,其核心价值在于能够根据业务场景(如数据实时性要求、会话隔离需求)正确选择和配置缓存策略,在提升性能的同时,精准规避“脏读”风险,构建高效且可靠的数据访问层。本文将从源码和实战角度,为你彻底厘清这两级缓存的奥秘。
一、 缓存全景图:MyBatis的两级缓存架构

首先建立宏观认知:MyBatis的缓存设计是分层级的。
一级缓存(Local Cache):也称为本地缓存或会话级缓存。其生命周期与一个SqlSession绑定,默认开启且无法关闭。
二级缓存(Second Level Cache):也称为应用级缓存或命名空间级缓存。其生命周期与一个SqlSessionFactory(即一个应用)绑定,需要手动配置开启,并可在多个SqlSession间共享。
理解这份MyBatis一级缓存与二级缓存原理区别,是合理使用它们的前提。在鳄鱼java的课程设计中,我们始终强调“先理解生命周期,再谈使用”。
二、 一级缓存深度解析:SqlSession的“私人备忘录”
1. 核心特征与生命周期
* 作用域:同一个SqlSession对象。当你执行查询时,结果会被缓存到该SqlSession内部的一个Map结构中。
* 默认状态:默认开启,无法全局禁用(但可通过配置影响其行为)。
* 存储位置:JVM堆内存中,属于进程内缓存。
2. 工作原理与代码透视
一级缓存本质上是一个基于`HashMap`的简单缓存,其键(CacheKey)由以下要素共同决定:
* Mapper Statement ID(方法全限定名)
* 查询的偏移量(RowBounds)
* 传递给SQL的参数值
* 环境ID(如数据库配置)
* 最终执行的SQL语句(BoundSql)
当在同一个SqlSession中执行两次完全相同的查询时,MyBatis会先根据上述要素生成一个CacheKey,然后在一级缓存的Map中查找。如果找到,则直接返回缓存对象,不再访问数据库。
3. 一级缓存的失效时机(至关重要!)
一级缓存并非永久有效,在以下操作后会自动清空(清除整个SqlSession内的缓存):
* 执行了INSERT、UPDATE、DELETE语句(无论是否影响本查询涉及的数据)。
* 手动调用`sqlSession.clearCache()`方法。
* 对Mapper配置文件中的`