MyBatis 缓存全面详解
一、缓存概述
1. 定义
缓存是一种存储技术,用于临时存储最近访问的数据,以便在需要时可以快速访问。通过减少对持久层的访问次数,缓存可以显著提高应用程序的性能和响应速度。
2. 特点
高速访问:缓存的存在减少了对数据库的访问,从而加快了数据的读取速度。
减少数据库压力:缓存减少了对数据库的频繁访问,降低了数据库的负载。
提高系统性能:缓存能够提高应用程序的响应速度,提升用户体验。
二、MyBatis 缓存机制
MyBatis 提供了两层缓存机制:一级缓存(Local Cache)和二级缓存(Second Level Cache)。
一级缓存
定义与特点
一级缓存是基于 SqlSession 级别的缓存,它是一个私有的、本地的缓存区域。一级缓存默认开启,它的作用范围是当前 SqlSession,当 SqlSession 关闭时,一级缓存随之失效。
工作原理
MyBatis 在执行 SQL 查询时,首先会检查一级缓存中是否已经存在相同 SQL 和参数的结果。如果存在,直接返回结果;如果不存在,则执行 SQL 查询,将结果存入一级缓存,并返回结果。
失效机制
当执行 CRUD(增删改) 操作时,一级缓存会失效,因为这些操作可能影响到查询结果。
当关闭 SqlSession 时,一级缓存也会失效。
二级缓存
定义与特点
二级缓存是基于 Mapper 接口级别的缓存,它是一个全局的缓存区域。二级缓存可以跨 SqlSession 共享数据,它的作用范围是整个 Mapper 接口。
工作原理
MyBatis 在执行 SQL 查询时,首先会检查二级缓存中是否已经存在相同 SQL 和参数的结果。如果存在,直接返回结果;如果不存在,则执行 SQL 查询,将结果存入二级缓存,并返回结果。
失效机制
当执行 CRUD 操作时,二级缓存会失效,因为这些操作可能影响到查询结果。
当 Mapper 接口中的 SQL 语句发生变化时,二级缓存会失效。
当关闭 Mapper 接口时,二级缓存也会失效。
全局配置文件(mybatis-config.xml)中启用二级缓存并设置全局属性:
<configuration>
<!-- 启用二级缓存 -->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<!-- 其他全局配置... -->
</configuration>
Mapper 映射文件中配置二级缓存具体参数:
<mapper namespace="com.example.mapper.UserMapper">
<!-- 开启该 mapper 的二级缓存,并配置缓存策略、容量大小等 -->
<cache eviction="LRU" size="1024" />
<!-- 查询语句或其他 SQL 映射... -->
<select id="getUserById" resultType="com.example.model.User">
SELECT * FROM users WHERE id = #{id}
</select>
</mapper>
注意,这里的 <cache> 标签是用来配置二级缓存的具体参数的,如驱逐策略(eviction)、缓存容量大小(size)等。
然而,在实际项目中,MyBatis 的二级缓存往往需要结合具体的缓存插件使用,例如 Ehcache 或 Redis 等第三方缓存工具,以提供更强大的功能,比如过期时间设置、分片管理以及更多的驱逐策略选择等。这部分配置通常会在对应的缓存插件的配置文件中完成,而不是直接在 MyBatis 的 XML 配置文件中体现。
以下是一个使用 Ehcache 作为二级缓存实现时,在 Ehcache 的配置文件(ehcache.xml)中的部分配置示例:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd">
<diskStore path="java.io.tmpdir"/>
<cache name="com.example.mapper.UserMapper"
maxEntriesLocalHeap="1000"
eternal="false"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LRU">
</cache>
<!-- 其他缓存区域配置... -->
</ehcache>
在这个例子中,我们为 UserMapper 配置了一个 Ehcache 缓存,设置了最大内存条目数、生存时间以及其他相关参数。这样,MyBatis 的二级缓存就会利用 Ehcache 提供的功能进行更高效的缓存管理。
查找顺序
当执行一个查询操作时,MyBatis 会先检查一级缓存(SqlSession 级别),若未命中,则继续查找二级缓存(Mapper 接口级别)。
若二级缓存中存在匹配的结果,则直接返回;否则,从数据库获取数据,并将结果分别存入一级缓存和二级缓存(根据配置决定是否存入二级缓存)。
4. 颗粒度详解
一级缓存的颗粒度:SqlSession 级别,作用范围是当前 SqlSession。
二级缓存的颗粒度:Mapper 接口级别,作用范围是整个 Mapper 接口。
数据一致性
为了保证缓存中的数据与数据库中的数据一致性,MyBatis 提供了一些策略,如在执行 CRUD 操作时自动清空缓存,以及在缓存中存储数据的版本信息等。
配置作用与好处
配置配置 MyBatis 缓存的主要目的是为了优化数据访问性能和资源利用率。通过合理设置缓存参数,可以带来以下好处:
提升查询性能:启用缓存后,对于相同的 SQL 查询,MyBatis 可以避免多次执行相同查询语句,从而显著降低数据库负担并提高应用程序响应速度。
节省系统资源:在高并发场景下,缓存能够有效减轻数据库服务器的压力,减少对硬件资源的消耗。
跨会话共享数据:二级缓存尤其适用于那些数据更新频率较低且需要跨多个 SqlSession 共享结果集的应用场景,如用户信息、静态数据等。
精细化控制:MyBatis 的缓存支持粒度级别的配置,允许开发人员针对不同业务需求选择性地开启或关闭缓存,以及调整缓存容量、驱逐策略等属性。
数据一致性保障:虽然缓存提高了性能,但也带来了数据一致性的挑战。通过正确配置缓存刷新策略和失效机制,可以确保缓存中的数据尽可能与数据库保持同步,防止出现因缓存导致的数据不一致问题。