MyBatis 缓存概述
缓存的概念和作用
- 缓存是数据交换的缓冲区(称作Cache),是临时存贮数据(一般是使用频繁的数据)的地方。当用户查询数据,首先在缓存中寻找,如果找到了则直接返回。如果找不到,则去数据的来源查找 。
- 缓存的本质就是用空间换时间,牺牲数据的实时性,以内存中的数据暂时替代从外部读取数据,达到减轻服务端压力,减少网络延迟的效果。
MyBatis 缓存
- MyBatis 提供的缓存,缓存的是数据库查询的结果。
MyBatis 日志配置
- 通过日志查看 MyBatis 的执行过程,执行过程反映了 MyBatis 是否使用了缓存。
- 参考官网:mybatis.org/mybatis-3/z…
- 第一步:引入 Log4j 依赖
- 第二步:配置 log4j.properties 文件
MyBatis 一级缓存
- MyBatis 一级缓存是 SqlSession 级别的,通过同一个 SqlSession 查询的结果会被缓存。下次查询相同的数据时,就会从缓存中直接获取,不会查询数据库。
- MyBatis 一级缓存是默认开启的。
CASE 1:同一个 SqlSession,相同的查询条件
只执行了一次数据库查询,第二次查询使用缓存中的数据。
CASE 2:同一个 SqlSession,不相同的查询条件
- 两次查询的条件不同,第二次查询未命中缓存,执行了两次数据库查询。
CASE 3:不同 SqlSession,相同的查询条件
一级缓存是 SqlSession 级别的,SqlSession 之间不能共用一级缓存。
CASE 4:同一个 SqlSession,不同的 mapper 对象
CASE 5:同一个 SqlSession,同一个 mapper,不同的方法,执行 SQL 相同
命中一级缓存要求以下相同:SqlSession,namespace,执行方法,SQL,参数。
CASE 6:第一次查询没有查到数据,第二次使用相同参数查询
“未查询到数据”也是查询结果,也会被缓存下来。
一级缓存失效的情况
- 不同的 SqlSession
- 同一个 SqlSession,不同的查询条件
- 缓存被清空
- SqlSession 内执行了增、删、改会清空一级缓存
- 执行 SqlSession 的 clearCache 方法会清空一级缓存
缓存被清空: SqlSession 内执行了增、删、改会清空一级缓存
为什么执行了增、删、改 MyBatis 就要清空一级缓存?
- 因为执行了 DML,数据库中的数据可能发生了变化,缓存中的数据可能过时了,要从数据库中获取最新数据
缓存被清空:执行 SqlSession 的 clearCache 方法会清空一级缓存
如何强制不使用一级缓存?
- 一级缓存的问题:数据实时性得不到保障。如果其他 SqlSession 变更了数据,当前 SqlSession 查到的可能就不是最新数据。
- 强制不使用一级缓存 在 mybatis-config.xml 核心配置文件中增加配置
MyBatis 二级缓存
- MyBatis 二级缓存是 SqlSessionFactory 级别的,通过同一个 SqlSessionFactory 创建的 SqlSession查询的结果会被缓存。下次查询相同的数据时,就会从缓存中直接获取,不会查询数据库。
- MyBatis 二级缓存是默认关闭的。
使用二级缓存的步骤
- mapper.xml 文件中添加标签
- POJO 类实现
Serializable
接口 - 关闭 session,一级缓存中的数据才会写入到二级缓存
- 执行增、删、改会清空二级缓存
MyBatis 缓存查询的顺序
- 先查询二级缓存,命中二级缓存则直接使用二级缓存中的数据
- 二级缓存未命中,查询一级缓存,一级缓存命中则直接使用一级缓存中的数据
- 一级缓存未命中,查询数据库,将查询结果存入一级缓存
- SqlSession 关闭,将一级缓存中的数据写入二级缓存
为什么不推荐使用 MyBatis 二级缓存
- 二级缓存的生命周期比一级缓存长,数据实时性更难以保障。
也可以通过配置刷新间隔让二级缓存定期失效,但刷新间隔需要配置得合理。