文章目录
一级缓存
一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问。(默认开启)
基本特性
- 默认开启:SqlSession 级别的缓存
- 作用范围:同一个 SqlSession
- 生命周期:与 SqlSession 一致
- 自动失效:执行 INSERT、UPDATE、DELETE 或清空缓存时
工作原理
java
// 示例:一级缓存演示
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 第一次查询,会访问数据库
User user1 = mapper.selectById(1L);
// 第二次查询相同数据,直接从一级缓存获取
User user2 = mapper.selectById(1L); // 不会访问数据库
// 执行更新操作
mapper.updateUser(user1);
// 再次查询,缓存已失效,会访问数据库
User user3 = mapper.selectById(1L); // 访问数据库
}
二级缓存
二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取。(默认关闭)
基本特性
- 默认关闭:需要手动开启
- 作用范围:Mapper 级别的缓存,跨 SqlSession
- 生命周期:只要不清理,一直存在
- 失效情况:两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效
如何开启
-
在核心配置文件(mybatis-config.xml)中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
xml<configuration> <settings> <!-- 默认为 true,通常无需显式配置 --> <setting name="cacheEnabled" value="true"/> </settings> </configuration> -
在mapper.xml中声明使用缓存
xml<select id="selectUser" resultType="User" useCache="false"> SELECT * FROM user WHERE id = #{id} </select> <mapper namespace="com.example.UserMapper"> <cache /> <!-- 开启二级缓存 --> <select id="selectById" resultType="User" useCache="true"> SELECT * FROM user WHERE id = #{id} </select> </mapper> -
或注解方式配置
java@CacheNamespace( eviction = LruCache.class, flushInterval = 60000, size = 512 ) public interface UserMapper { @Options(useCache = true) @Select("SELECT * FROM user WHERE id = #{id}") User selectById(Long id); } -
查询的数据所转换的实体类类型必须实现序列化的接口
javapublic class User implements Serializable { private static final long serialVersionUID = 1L; // ... } -
二级缓存必须在SqlSession关闭或提交之后有效
对比

MyBatis缓存查询的顺序
- 先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用;
- 如果二级缓存没有命中,再查询一级缓存;
- 如果一级缓存也没有命中,则查询数据库;
- SqlSession关闭之后,一级缓存中的数据会写入二级缓存。
总结
- 不要用二级缓存,生产环境一般用redis替代,避免数据不一致的问题。
- 一级缓存只在单次sqlsession中生效。
参考:
http://www.cppcns.com/ruanjian/java/727879.html
https://developer.aliyun.com/article/1613160
以上为个人学习分享,如有问题,欢迎指出:)