MyBatis 提供了缓存机制来提升数据库查询性能,避免重复执行相同的 SQL 语句,减轻数据库压力。其缓存分为一级缓存和二级缓存,两者的作用范围和生命周期不同。
1. 一级缓存(本地缓存,SqlSession 级缓存)
- 作用范围:仅限于当前 
SqlSession(会话),即同一个SqlSession内的查询会共享缓存。 - 生命周期:随 
SqlSession的创建而创建,随SqlSession的关闭(close())或提交(commit()/rollback())而清空。 - 默认行为:一级缓存默认开启,无需额外配置。
 - 工作原理:
- 当执行查询时,MyBatis 会先在一级缓存中查找是否存在相同的查询结果(通过 
Mapper ID + SQL 语句 + 参数 + 分页信息等作为缓存键)。 - 若存在,则直接返回缓存数据;若不存在,则执行 SQL 并将结果存入一级缓存。
 - 若在同一个 
SqlSession内执行了 增删改操作(insert/update/delete),MyBatis 会自动清空一级缓存,避免脏数据。 
 - 当执行查询时,MyBatis 会先在一级缓存中查找是否存在相同的查询结果(通过 
 
2. 二级缓存(全局缓存,Mapper 级缓存)
- 作用范围:跨 
SqlSession共享,作用于整个Mapper接口(或Mapper.xml),即同一个Mapper的所有SqlSession共享缓存。 - 生命周期:随应用启动而创建,随应用关闭而销毁(可通过配置调整过期策略)。
 - 开启方式:默认关闭,需手动配置:
- 在 
MyBatis全局配置文件(mybatis-config.xml)中开启二级缓存总开关(默认已开启,可省略):<settings> <setting name="cacheEnabled" value="true"/> </settings> - 在需要使用二级缓存的 
Mapper.xml中添加<cache/>标签(或在接口类上添加@CacheNamespace注解):<!-- Mapper.xml 中配置 --> <mapper namespace="com.example.UserMapper"> <cache eviction="LRU" <!-- 缓存回收策略:LRU(默认,最近最少使用)、FIFO、SOFT、WEAK --> flushInterval="60000" <!-- 自动刷新时间(毫秒),默认不刷新 --> size="1024" <!-- 最大缓存对象数量,默认 1024 --> readOnly="false"/> <!-- 是否只读:false(默认,可序列化对象)、true(返回缓存对象的引用) --> </mapper> 
 - 在 
 - 注意事项:
- 二级缓存的对象需实现 
Serializable接口(当readOnly=false时,避免序列化失败)。 - 若 
Mapper中某条 SQL 不需要使用二级缓存,可通过useCache="false"禁用:<select id="getUser" resultType="User" useCache="false"> SELECT * FROM user WHERE id = #{id} </select> - 执行增删改操作时,MyBatis 会自动清空当前 
Mapper的二级缓存(可通过flushCache="false"关闭自动清空,但不推荐,可能导致脏数据)。 
 - 二级缓存的对象需实现 
 
3. 一级缓存与二级缓存的执行顺序
当查询执行时,MyBatis 会先检查二级缓存,若未命中则检查一级缓存,若仍未命中则执行 SQL 查询,查询结果会依次存入一级缓存和二级缓存(若开启)。
4. 缓存的适用场景
- 适合缓存查询频率高、数据变化少的场景(如字典表、配置表)。
 - 不适合缓存实时性要求高、数据频繁变化的场景(如订单表、库存表)。
 
总结
- 一级缓存:默认开启,
SqlSession级,随会话销毁,无需配置。 - 二级缓存:需手动开启,
Mapper级,全局共享,需注意序列化和脏数据问题。 
注意:本文归作者所有,未经作者允许,不得转载