MyBatis 一级缓存和二级缓存的区别是什么?[^2]
时间: 2025-03-13 15:00:39 浏览: 37
<think>好的,我现在要仔细分析用户的问题,他想了解MyBatis一级缓存和二级缓存的区别及工作原理。首先,我需要回忆MyBatis缓存的相关知识,并结合提供的引用资料来组织答案。
根据用户提供的引用内容,引用[2]和[3]提到一级缓存是SqlSession级别的,默认开启,而二级缓存是Mapper级别的,默认关闭。引用[4]则说明了如何配置启用二级缓存,需要修改配置文件并在Mapper文件中添加缓存设置。此外,引用[2]和[3]都指出,二级缓存在增删改频繁的情况下可能无效,因为会被清空。
接下来需要明确两者的区别,可能包括作用域、开启状态、存储位置、失效机制等。例如,一级缓存存在于SqlSession的生命周期中,而二级缓存跨SqlSession,属于Mapper级别。一级缓存默认开启,二级缓存需要手动配置。存储位置上,一级缓存在内存,二级缓存可能使用外部存储如Redis。失效机制方面,一级缓存在执行update操作或关闭SqlSession时失效,二级缓存在整个Mapper的update操作后失效。
另外,需要解释工作原理。一级缓存如何工作:执行查询时先检查缓存,存在则直接返回,否则查询数据库并存入缓存。二级缓存则需要跨会话共享,可能涉及序列化问题,且需注意事务提交后才生效。
用户可能存在的疑问点包括:为什么二级缓存默认关闭?如何正确使用二级缓存?适用场景是什么?这些都需要在回答中涵盖。
需要确保回答结构清晰,分点说明区别,再详细各自的工作原理,最后总结注意事项。同时,引用资料中的信息要正确标注,如默认关闭的原因,配置方法等。
可能需要注意的问题:是否存在引用资料中的重复?比如引用[2]和[3]内容相似,需要确认是否不同来源,但用户提供的引用可能有重复,处理时应合并相同点。此外,确保术语准确,比如SqlSession、Mapper等。
最后,生成相关问题,可能涉及性能优化、配置步骤、使用场景等,根据用户提供的示例问题来参考结构。</think>### MyBatis 一级缓存与二级缓存的区别及工作原理
#### 一、核心区别
1. **作用域不同**
- **一级缓存**:作用于单个 `SqlSession` 生命周期内,缓存数据仅对当前会话可见[^2][^3]。
- **二级缓存**:作用于 `Mapper` 级别,多个 `SqlSession` 共享同一命名空间(Mapper接口)的缓存数据[^2][^3]。
2. **默认状态与配置**
- **一级缓存**:默认开启,无需额外配置[^3]。
- **二级缓存**:默认关闭,需在全局配置中启用(`cacheEnabled=true`),并在对应的 Mapper XML 文件中添加 `<cache/>` 标签[^4]。
3. **失效机制**
- **一级缓存**:
- 执行增删改(`INSERT/UPDATE/DELETE`)操作时自动清空当前 `SqlSession` 的缓存。
- 调用 `SqlSession.close()` 或 `SqlSession.clearCache()` 时清空。
- **二级缓存**:
- 执行同一 Mapper 的增删改操作时清空整个命名空间的缓存。
- 需注意事务提交后(`sqlSession.commit()`)才会生效。
4. **存储位置**
- **一级缓存**:基于内存(JVM 堆)存储,直接关联 `SqlSession` 对象。
- **二级缓存**:可通过配置使用第三方缓存(如 Redis、EhCache),支持跨会话持久化。
#### 二、工作原理
1. **一级缓存的工作流程**
- 查询时优先检查缓存,若命中则直接返回结果。
- 未命中则查询数据库,将结果存入缓存(键为 SQL 语句 + 参数 + 分页条件)。
- 执行更新操作或会话关闭时,清空缓存以保证数据一致性[^3]。
```java
// 示例:同一 SqlSession 内重复查询会命中缓存
User user1 = sqlSession.selectOne("getUserById", 1); // 查数据库
User user2 = sqlSession.selectOne("getUserById", 1); // 直接读缓存
```
2. **二级缓存的工作流程**
- 查询时先检查一级缓存,未命中则检查二级缓存。
- 二级缓存命中后,数据会反序列化并存入当前会话的一级缓存。
- 事务提交时,当前会话的一级缓存数据才会同步到二级缓存[^4]。
- 需注意:返回对象需实现 `Serializable` 接口,否则可能抛出序列化异常。
```xml
<!-- Mapper XML 中配置二级缓存 -->
<mapper namespace="com.example.UserMapper">
<cache/>
</mapper>
```
#### 三、注意事项
- **二级缓存的适用场景**:
- 数据读多写少,且对实时性要求不高(如配置表查询)[^3]。
- 若频繁执行增删改操作,二级缓存可能频繁失效,反而降低性能。
- **缓存一致性风险**:
- 分布式环境下,二级缓存需配合集中式缓存(如 Redis)避免数据不一致。
- **强制跳过缓存**:
- 可通过 `flushCache="true"` 属性强制清空缓存,例如:
```xml
<select id="getUser" resultType="User" flushCache="true"> ... </select>
```
阅读全文
相关推荐

















