好的,我们可以系统地聊聊 MyBatis 的缓存机制,这是 Java 开发中非常常见、面试中也常考的知识点。我们可以从 基本概念 → 一级缓存 → 二级缓存 → 使用场景与注意点 逐步讲。
1️⃣ MyBatis 缓存机制概述
MyBatis 提供 两级缓存:
| 缓存级别 | 作用域 | 生命周期 | 默认开启 |
|---|---|---|---|
| 一级缓存(Local Cache) | SqlSession 级别 | 与 SqlSession 生命周期一致 | 开启 |
| 二级缓存(Global Cache) | Mapper 级别 | 与 SqlSessionFactory 生命周期一致 | 关闭(需配置) |
- 目的:减少数据库访问次数,提高性能。
- 方式:基于 Map 实现,key 通常由 SQL 语句 + 参数生成。
2️⃣ 一级缓存(Local Cache)
- 作用域:同一个
SqlSession内。 - 原理:每次查询时,先检查缓存,如果有结果直接返回,否则查询数据库,并将结果放入缓存。
- 特点:
- 默认开启,不需要额外配置。
- 缓存键是 SQL + 参数。
- 一旦
SqlSession关闭,缓存失效。
- 示例:
SqlSession session = sqlSessionFactory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
// 第一次查询,走数据库
User user1 = mapper.selectById(1);
// 第二次查询,直接从缓存返回
User user2 = mapper.selectById(1);
session.close(); // 缓存失效
注意事项:
一级缓存会在以下情况下被清空:
- 执行
insert/update/delete操作。 - 手动调用
session.clearCache()。 - 不同
SqlSession之间不共享缓存。
3️⃣ 二级缓存(Global Cache)
- 作用域:同一个
Mapper的多个SqlSession共享。 - 原理:使用 序列化对象 + Map 来存储缓存数据。
- 开启方式:
- Mapper XML 文件中配置
<cache />。 - 开启全局缓存可选配置,如 eviction(回收策略)、flushInterval(刷新时间)、size(缓存大小)。
- Mapper XML 文件中配置
- 示例:
<mapper namespace="com.example.mapper.UserMapper">
<cache
eviction="LRU"
flushInterval="60000"
size="512"
readOnly="true"/>
</mapper>
Java 使用示例:
SqlSession session1 = sqlSessionFactory.openSession();
UserMapper mapper1 = session1.getMapper(UserMapper.class);
User user1 = mapper1.selectById(1);
session1.close(); // 数据写入二级缓存
SqlSession session2 = sqlSessionFactory.openSession();
UserMapper mapper2 = session2.getMapper(UserMapper.class);
User user2 = mapper2.selectById(1); // 从二级缓存获取
session2.close();
注意事项:
- 默认二级缓存是关闭的,需要
<cache />手动开启。 - 缓存只在同一个命名空间(Mapper)中生效。
- 更新操作会清空缓存。
- 对象必须可序列化(实现
Serializable)。
4️⃣ 一级缓存 vs 二级缓存
| 特性 | 一级缓存 | 二级缓存 |
|---|---|---|
| 作用域 | SqlSession | Mapper |
| 默认开启 | ✅ | ❌ |
| 生命周期 | SqlSession 存活期间 | SqlSessionFactory 存活期间 |
| 线程安全 | 不需要 | 需要(多线程共享) |
| 失效条件 | 更新/手动清除 | 更新/flushInterval/手动清除 |
5️⃣ 使用技巧
- 合理使用二级缓存:适合查询多、更新少的场景,如字典表、配置表。
- 注意对象可序列化:否则会报
NotSerializableException。 - 避免缓存穿透:查询条件频繁变化时,缓存命中率低,可能反而增加负担。
- 结合 MyBatis-Plus 或 Spring Cache:可以整合 Redis 做分布式缓存,扩展性更强。
如果你愿意,我可以画一张 MyBatis 一级缓存和二级缓存工作原理图,让你一眼就看懂数据是怎么流动的,特别适合面试讲解。
你希望我画吗?