MyBatis 提供了两级缓存机制:一级缓存和二级缓存。缓存失效机制在 MyBatis 中起着至关重要的作用,以确保数据的正确性和一致性。下面我们来详细了解 MyBatis 中一级缓存和二级缓存的失效机制。
1. 一级缓存失效机制
一级缓存 是 MyBatis 默认开启的缓存机制,作用范围是 SqlSession
级别。一级缓存的生命周期与 SqlSession
相同。它的失效机制如下:
1.1 一级缓存的默认行为
- 默认缓存 :在同一个
SqlSession
实例中,如果执行了相同的查询(相同的 SQL 语句和参数),MyBatis 会从一级缓存中获取结果,而不是重新访问数据库。
1.2 一级缓存的失效条件
以下几种情况会导致一级缓存失效:
-
执行了
INSERT
、UPDATE
或DELETE
操作:- 当在
SqlSession
中执行了增、删、改操作时,MyBatis 会清空一级缓存。这是为了确保数据一致性,因为增、删、改操作可能改变数据库中的数据,因此之前缓存的查询结果可能已经过时。
- 当在
-
手动清空缓存:
- 可以通过调用
SqlSession.clearCache()
方法手动清空一级缓存。这通常用于在特殊情况下主动刷新缓存。
- 可以通过调用
-
SqlSession
关闭:- 当
SqlSession
关闭时,一级缓存随之被销毁。不同的SqlSession
实例拥有各自独立的缓存。
- 当
-
执行不同的查询:
- 如果在
SqlSession
中执行了不同的查询(不同的 SQL 语句),MyBatis 不会使用之前缓存的结果。
- 如果在
2. 二级缓存失效机制
二级缓存 是 MyBatis 提供的全局缓存机制,作用范围是 Mapper
映射器级别。二级缓存默认是关闭的,必须显式开启。二级缓存的失效机制如下:
2.1 二级缓存的默认行为
-
缓存共享 :二级缓存是跨
SqlSession
的,同一个Mapper
映射器下的多个SqlSession
实例可以共享缓存的数据。 -
配置缓存 :二级缓存需要在 MyBatis 配置文件或
Mapper
文件中进行配置。可以通过<cache>
标签启用二级缓存,并设置缓存策略、刷新间隔等。
2.2 二级缓存的失效条件
二级缓存的失效机制主要包括以下几种情况:
-
执行了
INSERT
、UPDATE
或DELETE
操作:- 与一级缓存类似,当
Mapper
执行了增、删、改操作时,对应的二级缓存会被清空或标记为无效。这是为了确保其他SqlSession
实例能够获取最新的数据库数据。
- 与一级缓存类似,当
-
配置了缓存刷新间隔:
- 可以在
<cache>
标签中配置flushInterval
属性,指定缓存的刷新间隔时间。超过指定时间后,缓存将自动失效。
XML<cache flushInterval="60000" /> <!-- 缓存 60 秒后自动失效 -->
- 可以在
-
手动清空缓存:
- 可以通过
SqlSession.clearCache()
方法手动清空当前SqlSession
所关联的二级缓存。
- 可以通过
-
配置缓存大小:
- 可以通过
<cache>
标签中的size
属性配置缓存的最大对象数目。当缓存达到指定大小时,旧的缓存数据将被清除,以腾出空间存储新的数据。
XML<cache size="512" /> <!-- 缓存最多保存 512 个对象 -->
- 可以通过
-
配置缓存策略:
- 可以通过
eviction
属性配置缓存的回收策略,如 LRU(最近最少使用)、FIFO(先进先出)、SOFT(软引用)、WEAK(弱引用)。当缓存满时,根据策略清理旧数据。
XML<cache eviction="LRU" /> <!-- 使用 LRU 策略 -->
- 可以通过
-
使用
readOnly
属性:- 配置
readOnly
属性为true
时,缓存的数据将被标记为只读。在这种情况下,返回的对象会被共享,无法修改。
XML<cache readOnly="true" /> <!-- 缓存数据为只读,提升性能 -->
- 配置
3. 总结
-
一级缓存失效机制 :一级缓存作用于
SqlSession
级别,默认开启。当执行增删改操作、手动清空缓存、SqlSession
关闭或执行不同查询时,一级缓存将失效。 -
二级缓存失效机制 :二级缓存作用于
Mapper
映射器级别,默认关闭。可以通过配置启用二级缓存,并设置失效条件,如增删改操作、手动清空、刷新间隔、缓存策略等。
MyBatis 的缓存失效机制确保了数据的正确性和一致性,在适当的场景下使用缓存可以显著提升应用程序的性能,但同时也要注意缓存的失效条件,以避免因缓存数据不一致而导致的问题。