程序员求职经验分享与学习资料整理平台

网站首页 > 文章精选 正文

说说MyBatis的缓存机制(mybatis-plus缓存)

balukai 2025-07-28 15:13:36 文章精选 5 ℃

一句话总结

MyBatis采用两级缓存机制:

1. 一级缓存:SqlSession级别,默认开启,同一会话中相同查询直接复用缓存结果,执行更新操作或关闭会话时自动清空。

2. 二级缓存:Mapper级别,需手动开启,多个SqlSession共享,通过序列化机制实现跨会话缓存,支持LRU等淘汰策略。

两者均通过装饰器模式实现,可通过接口扩展集成第三方缓存(如Redis)。

详细解析

MyBatis 缓存分为一级缓存和二级缓存,两者在作用范围、生命周期和管理方式上存在显著差异。以下是详细的介绍:

1. 一级缓存(Local Cache)

核心特性

作用范围:SqlSession级别(同一个数据库会话)。

默认开启:无需额外配置。

生命周期:与SqlSession绑定,会话关闭或执行更新操作(增删改)时自动清空。

共享性:仅对当前SqlSession可见,其他会话无法访问。

工作原理

缓存命中:在同一个SqlSession中,若多次执行相同的 SQL 和参数,MyBatis 会直接从缓存中返回结果,避免重复查询数据库。

缓存失效:

执行INSERT、UPDATE、DELETE操作。

手动调用sqlSession.clearCache()。

提交事务(sqlSession.commit())或回滚事务(sqlSession.rollback())。

示例

SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

// 第一次查询,访问数据库
User user1 = mapper.selectUserById(1); 

// 第二次查询,命中一级缓存(不访问数据库)
User user2 = mapper.selectUserById(1); 

// 执行更新操作,清空缓存
mapper.updateUser(user1);
sqlSession.commit();

// 第三次查询,缓存已失效,重新访问数据库
User user3 = mapper.selectUserById(1); 

sqlSession.close();

2. 二级缓存(Second Level Cache)

核心特性

作用范围:Mapper级别(跨SqlSession)。

手动开启:需在 XML 或注解中显式配置。

生命周期:与应用生命周期一致,直到缓存被主动清除或配置过期。

共享性:多个SqlSession共享同一 Mapper 的缓存。

配置方式

1、全局开启:在mybatis-config.xml中启用二级缓存

<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>

2、Mapper 级配置:在 Mapper XML 中添加<cache/>标签:

<mapper namespace="com.example.UserMapper">
    <cache eviction="LRU" flushInterval="60000" size="1024"/>
</mapper>

参数说明:

  • eviction:缓存淘汰策略(默认LRU,可选FIFO、SOFT、WEAK)。
  • flushInterval:自动刷新间隔(毫秒)。
  • size:缓存最大对象数量。

工作原理

  • 缓存命中:多个SqlSession执行相同 SQL 时,若二级缓存存在数据,直接返回结果。
  • 缓存失效:

执行INSERT、UPDATE、DELETE操作(同一 Mapper)。

手动调用sqlSession.clearCache()或通过配置自动刷新。

示例:

<!-- UserMapper.xml -->
<mapper namespace="com.example.UserMapper">
    <cache eviction="LRU"/>

    <select id="selectUserById" resultType="User" useCache="true">
        SELECT * FROM user WHERE id = #{id}
    </select>
</mapper>

3. 缓存优先级与执行流程

当同时启用一级和二级缓存时,MyBatis 按以下顺序查询数据:

一级缓存:优先检查当前SqlSession的缓存。

二级缓存:若一级缓存未命中,检查二级缓存。

数据库查询:若两级缓存均未命中,执行 SQL 查询,并将结果写入缓存。

4. 缓存使用注意事项

适用场景

一级缓存:适合单次会话内重复查询(如循环中多次查询同一数据)。

二级缓存:适合读多写少且数据实时性要求不高的场景(如配置表、静态数据)。

常见问题

脏读:

若多个SqlSession修改同一数据,二级缓存可能返回过期数据。

解决方案:合理设置flushInterval或在更新操作后手动清除缓存。

序列化问题:

二级缓存默认将对象序列化存储,实体类需实现Serializable接口。

分布式环境:

默认二级缓存是单机缓存,分布式系统中需集成 Redis、Ehcache 等分布式缓存框架。

5. 扩展:自定义缓存

MyBatis 支持集成第三方缓存库(如 Redis、Ehcache)替换默认的 PerpetualCache。

步骤(以 Redis 为例):

添加 Redis 依赖:

<dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-redis</artifactId>
    <version>1.0.0-beta2</version>
</dependency>

配置 Mapper 使用 Redis 缓存:

<mapper namespace="com.example.UserMapper">
    <cache type="org.mybatis.caches.redis.RedisCache"/>
</mapper>
最近发表
标签列表