目录
[2.2Mapper XML 中启用:](#2.2Mapper XML 中启用:)
[2.3.注解方式启用(实体类需实现 Serializable)](#2.3.注解方式启用(实体类需实现 Serializable))
[四、一级缓存 vs 二级缓存:核心差异](#四、一级缓存 vs 二级缓存:核心差异)
前言
作为 Java 开发者最常用的 ORM(Object-Relational Mapping,对象关系映射) 框架之一,MyBatis 的缓存机制是提升数据库访问性能的关键利器。理解其一级缓存和二级缓存的原理与差异,能让你在开发中做出更优化的选择。下面我们深入剖析这两级缓存的核心机制。
**一、**为什么需要缓存?
在数据库访问中,频繁执行相同 SQL 会导致:
-
网络开销:重复连接数据库消耗资源
-
数据库压力:增加数据库服务器负载
-
响应延迟:重复查询降低应用响应速度
MyBatis 通过两级缓存机制,将查询结果暂存于内存中,避免不必要的数据库交互,显著提升性能。
二、一级缓存:会话级的高速便签
1.核心特性
-
作用域:单个SqlSession范围内(数据库会话期间,从创建SqlSession会话,到提关闭会话)
-
默认开启:无需配置,自动生效
-
存储位置:SqlSession对象内部
2.工作流程示例:
java
try (SqlSession session = sqlSessionFactory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
// 首次查询,访问数据库并将结果存入一级缓存
User user1 = mapper.selectUserById(1);
// 再次查询相同数据,直接从一级缓存获取
User user2 = mapper.selectUserById(1);
System.out.println(user1 == user2); // 输出 true,同一对象!
}
3.缓存失效场景
(1)执行写操作 :**insert/update/delete
**会清空当前会话缓存
java
mapper.updateUser(user); // 执行后,一级缓存被清空
User user3 = mapper.selectUserById(1); // 重新查询数据库
(2)手动清空 :调用 session.clearCache()
java
try (SqlSession session = sqlSessionFactory.openSession()) {
UserMapper userMapper = session.getMapper(UserMapper.class);
// 第一次查询,数据存入缓存
User user1 = userMapper.selectUserById(1);
System.out.println("第一次查询: " + user1.getName());
// 手动清空一级缓存
session.clearCache();
System.out.println("手动清空缓存");
// 第二次查询,缓存已清空,重新查询数据库
User user2 = userMapper.selectUserById(1);
System.out.println("清空缓存后查询: " + user2.getName());
}
(3)会话结束 :SqlSession
关闭后缓存自动销毁
java
//第一个会话
SqlSession session1 = sqlSessionFactory.openSession();
UserMapper mapper1 = session1.getMapper(UserMapper.class);
User user1 = mapper1.selectUserById(1); // 从数据库查询
System.out.println("会话1第一次查询: " + user1.getName());
User user2 = mapper1.selectUserById(1); // 从一级缓存获取
System.out.println("会话1第二次查询: " + user2.getName());
// 关闭会话1,其缓存随之销毁
session1.close();
// 第二个新会话
SqlSession session2 = sqlSessionFactory.openSession();
UserMapper mapper2 = session2.getMapper(UserMapper.class);
// 由于是新会话,没有缓存,会从数据库查询
User user3 = mapper2.selectUserById(1);
System.out.println("新会话查询: " + user3.getName());
session2.close();
关键点 :一级缓存的生命周期与数据库会话绑定,适用于同一事务内重复查询的优化。
三、二级缓存:跨会话的共享数据池
1.核心特性
-
作用域 :Mapper 级别(跨
SqlSession
)即同一个命名空间下的所有 SQL 操作共享该缓存。 -
默认关闭:需手动在配置或映射文件中启用
-
存储位置:可配置(默认内存,支持集成 Redis/Ehcache)
2.启用与配置
2.1全局开启(mybatis-config.xml):
XML
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
2.2Mapper XML 中启用:
java
<mapper namespace="com.example.UserMapper">
<cache
eviction="LRU" <!-- 淘汰策略:最近最少使用 -->
flushInterval="60000" <!-- 自动刷新时间:1分钟 -->
size="512" <!-- 最大缓存对象数:512个 -->
readOnly="false" <!-- 缓存是否只读(false表示可读写) -->
/>
</mapper>
2.2.1 eviction
:缓存淘汰策略
当缓存空间不足(达到 size
限制)时,MyBatis 会根据该策略移除部分缓存数据,释放空间。常见取值:
-
LRU(Least Recently Used,默认值) :移除最近最少使用 的缓存对象(基于访问时间,很久未被访问的数据优先淘汰)。
适合:大部分场景,优先保留热点数据。
-
FIFO(First In First Out) :按照缓存对象的存入顺序 淘汰,先存入的先被移除。
适合:数据访问顺序性较强的场景。
-
SOFT :基于 JVM 的软引用(Soft Reference)淘汰,当 JVM 内存不足时,才会回收软引用对象。
适合:希望尽可能利用内存缓存,但允许在内存紧张时释放的场景。
-
WEAK :基于 JVM 的弱引用(Weak Reference)淘汰,只要发生垃圾回收,弱引用对象就会被回收。
适合:缓存数据可以随时被回收,不占用过多内存的场景。
2.2.2 flushInterval
:缓存自动刷新时间(毫秒)
设置缓存的过期时间,当缓存存在时间超过该值时,会被自动清空(无论是否被访问)。
-
单位:毫秒(如
60000
表示 1 分钟)。 -
默认值:
null
(即不自动刷新,缓存仅在执行写操作或手动清空时更新)。 -
适用场景:数据会定期更新,但更新频率可预测的场景(如每小时更新一次的统计数据)。
2.2.3 size
:最大缓存对象数量
控制缓存中最多可存储的对象数量(而非字节大小),超过该数量时会触发 eviction
策略淘汰旧数据。
-
默认值:
1024
(即最多缓存 1024 个对象)。 -
需根据实际场景调整:
-
设太小:可能频繁触发淘汰,缓存命中率低。
-
设太大:占用内存过多,可能影响系统性能。
-
2.3.注解方式启用(实体类需实现 Serializable
)
java
@CacheNamespace(eviction = LruCache.class, flushInterval = 60000, size = 512)
public interface UserMapper {
@Select("SELECT * FROM users WHERE id=#{id}")
User selectUserById(int id);
}
3.工作流程:
java
try (SqlSession session1 = factory.openSession()) {
UserMapper mapper1 = session1.getMapper(UserMapper.class);
User user1 = mapper1.selectUserById(1); // 查询数据库,结果存入二级缓存
}
try (SqlSession session2 = factory.openSession()) {
UserMapper mapper2 = session2.getMapper(UserMapper.class);
User user2 = mapper2.selectUserById(1); // 从二级缓存直接获取!
}
四、一级缓存 vs 二级缓存:核心差异

五、适用场景
-
一级缓存适用:
-
同一事务中多次获取用户信息
-
循环内重复查询同一数据
-
-
二级缓存适用:
-
全局配置项(如系统参数)
-
热点商品信息展示
-
低频更新的基础数据(如省份列表)
-
总结
MyBatis 的两级缓存是提升性能的利器,但需理解其内在机制:
-
一级缓存:轻量高效,自动管理,注意会话边界
-
二级缓存:威力强大,需谨慎配置,严防脏数据
正确使用缓存可使应用性能提升数倍!建议在开发中根据数据特性和访问模式灵活选择缓存策略,并通过监控工具(如 VisualVM)观察缓存命中率,持续优化配置。