首页 > 其他分享 >13. 说说 MyBatis 的缓存机制?

13. 说说 MyBatis 的缓存机制?

时间:2024-09-07 14:54:39浏览次数:9  
标签:Mapper 13 缓存 二级缓存 查询 SqlSession MyBatis

MyBatis 提供了一级缓存和二级缓存两种缓存机制,用于提高应用程序的性能,减少数据库的访问次数。缓存机制是 MyBatis 的一个重要特性,通过缓存可以在一定程度上减少对数据库的访问,从而提高查询性能。

1. 一级缓存(Local Cache)

作用范围:一级缓存是 MyBatis 默认开启的缓存机制,作用于 SqlSession 级别。

特点

  • 生命周期:一级缓存的生命周期与 SqlSession 相同。在同一个 SqlSession 中执行多次相同的查询(条件相同),如果缓存中已经存在结果,则直接返回缓存中的结果,而不再向数据库发送查询请求。

  • 存储方式:一级缓存是基于 PerpetualCache 和 HashMap 实现的,存储查询结果的键值对,键为 SQL 语句的字符串及其参数,值为查询结果。

  • 失效条件:在 SqlSession 中,如果执行了 INSERTUPDATEDELETE 操作,一级缓存会被清空,确保数据的一致性。另外,手动清空缓存或关闭 SqlSession 也会使一级缓存失效。

示例

SqlSession session = sqlSessionFactory.openSession();
User user1 = session.selectOne("selectUserById", 1); // 从数据库查询
User user2 = session.selectOne("selectUserById", 1); // 从一级缓存中获取结果

2. 二级缓存(Global Cache)

作用范围:二级缓存是 MyBatis 的全局缓存机制,作用于 Mapper 映射器级别。即同一个 Mapper 映射器中的查询结果可以被不同的 SqlSession 实例共享。

特点

  • 默认关闭:二级缓存默认是关闭的,需要在配置文件或 Mapper 文件中显式开启。

  • SqlSession:二级缓存是跨 SqlSession 的,多个 SqlSession 可以共享同一个 Mapper 中的缓存数据。

  • 存储方式:二级缓存也是基于 PerpetualCache 实现的,并且需要将缓存对象序列化,因此缓存对象必须实现 Serializable 接口。

  • 失效条件:当执行 INSERTUPDATEDELETE 等修改操作时,二级缓存会被清空。同时,事务提交后,查询结果才会写入二级缓存。

启用二级缓存

  1. 在 MyBatis 全局配置文件中启用二级缓存

    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
  2. 在具体的 Mapper 文件中配置二级缓存

    <mapper namespace="com.example.mapper.UserMapper">
        <!-- 启用二级缓存 -->
        <cache />
        
        <select id="selectUserById" resultType="User">
            SELECT * FROM user WHERE id = #{id}
        </select>
    </mapper>

示例

// 第一次查询,结果存入二级缓存
try (SqlSession session1 = sqlSessionFactory.openSession()) {
    UserMapper mapper1 = session1.getMapper(UserMapper.class);
    User user1 = mapper1.selectUserById(1);
}
​
// 第二次查询,不同的 SqlSession 实例,结果从二级缓存中获取
try (SqlSession session2 = sqlSessionFactory.openSession()) {
    UserMapper mapper2 = session2.getMapper(UserMapper.class);
    User user2 = mapper2.selectUserById(1);
}

3. 一级缓存与二级缓存的比较

特性一级缓存二级缓存
作用范围SqlSession 级别Mapper 映射器级别,跨 SqlSession
默认状态默认开启默认关闭
缓存生命周期SqlSession 相同Mapper 相同
缓存失效SqlSession 执行写操作时清空Mapper 执行写操作时清空
缓存共享不同的 SqlSession 之间不共享不同的 SqlSession 之间共享

4. 配置和管理二级缓存

MyBatis 提供了多种方式来配置和管理二级缓存:

  • 缓存策略:可以通过 <cache> 标签的 eviction 属性配置缓存回收策略。默认使用 LRU(最近最少使用),其他选项包括 FIFO(先进先出)、SOFT(软引用)、WEAK(弱引用)。

  • 刷新间隔:通过 flushInterval 属性配置缓存的刷新间隔。默认情况下不会自动刷新,可以设置为毫秒级的刷新间隔。

  • 缓存大小:通过 size 属性设置缓存的最大对象数量。

  • 只读模式:通过 readOnly 属性设置缓存是否为只读模式。只读模式下,缓存中的对象在缓存期间不可修改,适合提高并发性能。

示例配置

<cache 
    eviction="FIFO" 
    flushInterval="60000"  <!-- 缓存60秒刷新一次 -->
    size="512"              <!-- 缓存中最多保存512个对象 -->
    readOnly="true"         <!-- 只读缓存,提升并发性能 -->
/>

5. 使用注意事项

  • 事务管理:二级缓存和事务管理紧密相关,只有在事务提交后,查询结果才会存入二级缓存。如果事务回滚,缓存不会更新。

  • 对象序列化:由于二级缓存需要将对象序列化,所有被缓存的对象必须实现 Serializable 接口。

  • 一致性问题:二级缓存会在更新数据时失效,但在高并发情况下,可能会有短暂的缓存不一致问题,需要根据实际情况权衡缓存带来的性能提升与一致性问题。

6. 总结

  • 一级缓存:每个 SqlSession 维护自己的一级缓存,默认开启,不同 SqlSession 之间不共享。适用于单个会话内重复查询的场景。

  • 二级缓存:二级缓存是跨 SqlSession 的全局缓存,默认关闭,需要手动开启和配置。适用于多次会话之间需要共享查询结果的场景。

通过合理配置 MyBatis 的一级和二级缓存,可以显著提升应用程序的性能,特别是在读多写少的场景中,缓存机制可以有效减少数据库访问次数,提升查询效率。

标签:Mapper,13,缓存,二级缓存,查询,SqlSession,MyBatis
From: https://blog.csdn.net/zhzjn/article/details/141996159

相关文章

  • springboot+vue+mybatis河北经贸大学勤工助学系统+PPT+论文+讲解+售后
    河北经贸大学勤工助学系统是学校中重要的一环,勤工助学是教师、学生获取信息的主要渠道。于是经过考虑之后决定开发基于JSP技术设计与实现了一款简洁、轻便的河北经贸大学勤工助学系统。本系统解决了考勤的主要问题,包括以下多个功能模块:学生、教师、教师考勤、岗位类型、岗位......
  • 用空间清理调理风13重要物品14别人的杂物15杂乱与风水符号学
    13重要物品在清理杂物时,别忘了大件东西。你一直讨厌的那件可怕的旧家具、堵塞客厅的三角钢琴、你从来不用的卷起来的地毯、后院生锈的汽车、角落里积满灰尘的十年前瑞士奶酪植物。有些东西非常大,搬动它们是一项挑战,所以你要学会看穿它们的艺术,就像它们不再存在一样。你也许可以......
  • ctfshow web13
     尝试 常规姿势上传文件打开网站初步判定为文件上传漏洞。随便选择几个文件上传,提示错误不选择任何文件直接点提交也会报错打开burpsuite抓包,改掉MIME类型,也就是图示位置,发现也不行,应该不是MIME过滤一头雾水,只能换个思路。 -------------------------......
  • HTTP协议基本知识点:工作原理、http请求、响应、连接以及缓存机制
    目录一、HTTP概述二、HTTP的版本三、HTTP请求1.请求方法2.请求头四、HTTP响应1.状态码2.响应头五、HTTP持久连接六、缓存机制1.CacheControl2.ETag3.LastModified七、安全性八、使用场景总结 一、HTTP概述 全称:超文本传输协议(HyperTextTransferProtoco......
  • rk3566 rk3588 Android11/13 给内置APP添加相关权限,无需手动同意APP权限
    现象:打开APP会跳出权限弹窗,给APP相关权限才能够使用APP。目录1、adb查看logcat2、在SystemUIService.java内给APP添加加权限3、开机自启动APP4、executeCMD函数1、adb查看logcat打开APP,logcat会打印APP包名。我这边包名是com.jhooit.endoscope2、在SystemUIService.......
  • [ABC137F] Polynomial Construction 题解
    明明有最厉害最好想的插值做法,怎么没有人写呢。思路考虑\(n\)个点可以确定一个\(n-1\)次多项式。如何确定。令\(l_i(x)=\prod_{j\not=i}\frac{(x-x_j)}{(x_i-x_j)}\)。可以发现这个多项式在\(x=x_i\)时值为一,在\(x=x_j(j\not=i)\)时值为零。那么就有:\[F(x)=\su......
  • mybatis-plus打印完整sql
     importlombok.extern.slf4j.Slf4j;importorg.apache.ibatis.cache.CacheKey;importorg.apache.ibatis.executor.Executor;importorg.apache.ibatis.mapping.BoundSql;importorg.apache.ibatis.mapping.MappedStatement;importorg.apache.ibatis.mapping.Paramet......
  • CF1307(模拟赛记录)
    比赛页面偶然发现一道做过的G;C的罚时:没开longlong,谨记。然后一个小时没想出E……E题面:在一年成功的牛奶生产后,FarmerJohn奖励他的奶牛们它们最喜欢的美味的草。在田里有\(n\)个单位的排成一行的草,每个单位的草有甜味\(s_i\)。FarmerJohn有\(m\)头奶牛,每只都......
  • 2024.9.6 CF1307 模拟赛记录
    A:各捆干草间互相独立,所以优先移动距\(1\)近的。点击查看代码#include<bits/stdc++.h>#defineintlonglong#definepsbkpush_back#definefstfirst#definescdsecond#defineumapunordered_map#definepqueuepriority_queue#definevcvector#defineendl'\n'......
  • 深入探讨 MyBatis-Plus 的 LambdaQueryWrapper (方法使用大全+案例)
    个人名片......