目录
1. 缓存机制介绍
2. 一级缓存
3. 二级缓存
4. mybatis缓存执行流程
1. 缓存机制介绍
MyBatis 的缓存机制是为了提高应用程序的性能而设计的,通过缓存策略来减少数据库的查询次数。MyBatis 提供了两种类型的缓存:一级缓存和二级缓存。
- 默认情况下,只有一级缓存(session级别的缓存,也称为本地缓存)开启。
- 默认情况下,二级缓存是关闭的,需要显式启用。
- 为了提高扩展性。MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存
一级缓存和二级缓存图示
2. 一级缓存
一级缓存是默认启用的,它是基于 SqlSession 的缓存。这意味着在同一个 SqlSession 的生命周期内,对于相同的 SQL 查询,MyBatis 会先检查缓存中是否有之前执行该查询的结果,如果有,则直接从缓存中获取,而不是再次执行 SQL 查询。
- 作用范围:一级缓存的作用范围仅限于同一个 SqlSession。
- 自动管理:一级缓存由 MyBatis 自动管理,无需任何配置。
- 失效条件:
- 当执行更新操作(包括 insert、update 或 delete)时,一级缓存会被清空。
- 当 SqlSession 关闭或执行了 clearCache() 方法时,一级缓存也会被清空。
- 如果 SqlSession 设置了 autoCommit 为 true 并且执行了 commit,那么缓存也会被清空。
- 将一级缓存的作用域设置为语句级别(
localCacheScope
设置为STATEMENT
)
一级缓存启用测试
【说明】上面代码表明,测试方法中调用了两次查询方法,但是sql语句就执行了一次就得到了结果,这说明第一次查询后会记录在一级缓存中,如果再次执行sql语句时就会向一级缓存中查看是否此次qlSession会话中是否已经执行过该sql,执行过,就直接到缓存中拿结果,未执行,就向数据库中查询。
(一句换:相同的sql语句,没必要执行,到一级缓存中直接拿)
一级缓存失效测试(以执行了 clearCache() 方法时为例)
【说明】因为清空了一级缓存,则第二次同样的查询语句在一级缓存中没有找到,就只能向数据找了,所以就执行了两次sql语句。但是为啥查询的对象的属性值相同,确输出 false (地址值不同)?
这是因为第一次查询的结果
user1
和第二次查询的结果user2
尽管具有相同的属性值,但由于它们是由两次不同的数据库查询创建的,因此它们是两个不同的对象实例。因此,user1 == user2
返回false
,表示这两个对象的内存地址不同。
3. 二级缓存
二级缓存是一种可选的缓存机制,它在同一个命名空间(namespace)下的多个 SqlSession 之间共享数据。这意味着如果多个 SqlSession 执行相同的查询语句并且这些 SqlSession 都属于同一个命名空间,那么它们就可以共享缓存中的数据。
- 作用范围:二级缓存的作用范围是全局的,可以在不同的 SqlSession 实例间共享数据。
- 启用方式:
- 为了启用二级缓存,需要在 配置文件
<mapper>
标签中加入<cache/>
元素。 - 默认情况下,二级缓存是关闭的,需要显式启用。
- 你可以为每个
<mapper>
定制缓存策略,例如设置缓存过期时间、缓存存储机制等。
- 为了启用二级缓存,需要在 配置文件
- 失效条件:
- 默认情况下,当执行了更新操作后,二级缓存不会被清空,除非显式配置。
- 二级缓存可以通过调用
clear()
方法来手动清空。 - 二级缓存的数据一致性问题需要特别注意,因为它可能在多个线程或多个事务之间共享。
配置二级缓存代码
<mapper namespace="com.example.mapper.UserMapper">
<cache type="PERPETUAL" eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
<!-- SQL 映射 -->
</mapper>
各个参数说明
type
: 缓存实现类型,默认为 PERPETUAL(永不过期),可以改为其他实现,如 EHCache。eviction
: 指定缓存淘汰策略,默认为 LRU(最近最少使用)。flushInterval
: 指定缓存刷新间隔时间(毫秒),默认不自动刷新。size
: 缓存的最大容量。readOnly
: 如果设置为 true,则缓存中的数据被认为是只读的,这样在执行更新操作时就不会刷新缓存。
【注意】
1. 二级缓存可能会导致数据一致性问题,因此建议在只读操作或者对数据一致性要求较 低的应用中使用。
2. 对于需要更新操作的场景,应该谨慎使用二级缓存,以避免潜在的数据不一致问题。
4. mybatis缓存执行流程
总流程
查询开始:
- 当执行一个 SQL 查询时,MyBatis 会首先检查一级缓存中是否存在相同 SQL 语句的结果。
一级缓存命中:
- 如果一级缓存中有对应的查询结果,MyBatis 将直接从一级缓存中获取结果,而不执行 SQL 语句。
- 这个结果将被返回给调用者。
一级缓存未命中:
- 如果一级缓存中没有找到查询结果,MyBatis 会检查二级缓存(如果启用)。
二级缓存命中:
- 如果二级缓存中有对应的查询结果,MyBatis 将直接从二级缓存中获取结果,而不执行 SQL 语句。
- 这个结果将被返回给调用者。
二级缓存未命中:
- 如果二级缓存中也没有找到查询结果,MyBatis 会执行 SQL 语句,并将结果保存到一级缓存中(默认)和二级缓存中(如果启用)。
- 这个结果同样会被返回给调用者。
缓存失效:
- 当执行了更新操作(包括 insert、update 或 delete)时,一级缓存会被清空。
- 二级缓存默认不会被清空,但可以配置为在执行更新操作后清空。