总结
MyBatis采用两级缓存机制:
1. 一级缓存:SqlSession级别,默认开启,同一会话中相同查询直接复用缓存结果,执行更新操作或关闭会话时自动清空。
2. 二级缓存:Mapper级别,需手动开启,多个SqlSession共享,通过序列化机制实现跨会话缓存,支持LRU等淘汰策略。
两者均通过装饰器模式实现,可通过接口扩展集成第三方缓存(如Redis)。
详细解析
MyBatis 缓存分为一级缓存和二级缓存,两者在作用范围、生命周期和管理方式上存在显著差异。以下是详细的介绍:
1. 一级缓存(Local Cache)
核心特性
- 作用范围:SqlSession级别(同一个数据库会话)。
- 默认开启:无需额外配置。
- 生命周期:与SqlSession绑定,会话关闭或执行更新操作(增删改)时自动清空。
- 共享性:仅对当前SqlSession可见,其他会话无法访问。
工作原理
- 缓存命中:在同一个SqlSession中,若多次执行相同的 SQL 和参数,MyBatis 会直接从缓存中返回结果,避免重复查询数据库。
- 缓存失效:
- 执行INSERT、UPDATE、DELETE操作。
- 手动调用sqlSession.clearCache()。
- 提交事务(sqlSession.commit())或回滚事务(sqlSession.rollback())。
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
2. 二级缓存(Second Level Cache)
核心特性
- 作用范围:Mapper级别(跨SqlSession)。
- 手动开启:需在 XML 或注解中显式配置。
- 生命周期:与应用生命周期一致,直到缓存被主动清除或配置过期。
- 共享性:多个SqlSession共享同一 Mapper 的缓存。
配置方式
- 全局开启:在mybatis-config.xml中启用二级缓存:
1
2
3
<
settings
>
<
setting
name
=
"cacheEnabled"
value
=
"true"
/>
</
settings
>
- Mapper 级配置:在 Mapper XML 中添加<cache/>标签:
1
2
3
<
mapper
namespace
=
"com.example.UserMapper"
>
<
cache
eviction
=
"LRU"
flushInterval
=
"60000"
size
=
"1024"
/>
</
mapper
>
- 参数说明:
- eviction:缓存淘汰策略(默认LRU,可选FIFO、SOFT、WEAK)。
- flushInterval:自动刷新间隔(毫秒)。
- size:缓存最大对象数量。
- 参数说明:
工作原理
- 缓存命中:多个SqlSession执行相同 SQL 时,若二级缓存存在数据,直接返回结果。
- 缓存失效:
- 执行INSERT、UPDATE、DELETE操作(同一 Mapper)。
- 手动调用sqlSession.clearCache()或通过配置自动刷新。
示例
1 2 3 4 5 6 7 8 |
|
3. 缓存优先级与执行流程
当同时启用一级和二级缓存时,MyBatis 按以下顺序查询数据:
- 一级缓存:优先检查当前SqlSession的缓存。
- 二级缓存:若一级缓存未命中,检查二级缓存。
- 数据库查询:若两级缓存均未命中,执行 SQL 查询,并将结果写入缓存。
4. 缓存使用注意事项
适用场景
- 一级缓存:适合单次会话内重复查询(如循环中多次查询同一数据)。
- 二级缓存:适合读多写少且数据实时性要求不高的场景(如配置表、静态数据)。
常见问题
- 脏读:
- 若多个SqlSession修改同一数据,二级缓存可能返回过期数据。
- 解决方案:合理设置flushInterval或在更新操作后手动清除缓存。
- 序列化问题:
- 二级缓存默认将对象序列化存储,实体类需实现Serializable接口。
- 分布式环境:
- 默认二级缓存是单机缓存,分布式系统中需集成 Redis、Ehcache 等分布式缓存框架。
5. 扩展:自定义缓存
MyBatis 支持集成第三方缓存库(如 Redis、Ehcache)替换默认的 PerpetualCache。
步骤(以 Redis 为例):
- 添加 Redis 依赖:
1
2
3
4
5
<
dependency
>
<
groupId
>org.mybatis.caches</
groupId
>
<
artifactId
>mybatis-redis</
artifactId
>
<
version
>1.0.0-beta2</
version
>
</
dependency
>
- 配置 Mapper 使用 Redis 缓存:
1
2
3
<
mapper
namespace
=
"com.example.UserMapper"
>
<
cache
type
=
"org.mybatis.caches.redis.RedisCache"
/>
</
mapper
>
6. 总结
缓存类型 | 作用范围 | 配置方式 | 适用场景 | 注意事项 |
---|---|---|---|---|
一级缓存 | SqlSession | 默认开启 | 会话内重复查询 | 更新操作自动失效 |
二级缓存 | Mapper | 需显式配置<cache/> | 跨会话共享的静态数据 | 避免脏读,需序列化支持 |
自定义缓存 | 全局/分布式 | 集成第三方库 | 高并发、分布式系统 | 需解决数据一致性问题 |