MyBatis 学习(七)之 缓存

目录

1 MyBatis 缓存介绍

2 一级缓存

3 二级缓存

3.1 二级缓存介绍

3.2 二级缓存配置

3.3 二级缓存测试

4 参考文档


1 MyBatis 缓存介绍

        MyBatis 缓存是 MyBatis 中的一个重要特性,用于提高数据库查询的性能。MyBatis 提供了一级缓存和二级缓存两种类型的缓存机制。

  • 一级缓存:一级缓存(本地缓存)是 MyBatis 中默认的缓存机制,它是 SqlSession 级别的缓存。当使用 SqlSession 执行一次查询时,查询到的结果集会存储在 SqlSession 的缓存中。当使用 SqlSession 再次执行相同的查询时,它会首先从缓存中获取结果,而不会再次查询数据库。一级缓存是基于事务的,当 SqlSession flush(插入、更新、修改) 或 close 后,该 SqlSession 中的所有 Cache 将被清空

  • 二级缓存:二级缓存是 Mapper 级别的缓存,也称为 namespace 级别。这意味着无论通过哪个 SqlSession 执行相同的 Mapper 接口操作,都可以访问到相同的二级缓存数据,即跨 SqlSession 共享同一 Mapper 接口的数据。二级缓存需要手动配置,它可以实现更大范围的数据共享和更高效的查询性能。二级缓存也可以配置为使用不同的缓存实现,如 Ehcache、Redis 等

        MyBatis 缓存的主要作用是减少对数据库的访问次数,提高查询性能。然而,需要注意的是,缓存也会占用内存空间,如果缓存的数据量过大,可能会导致内存溢出的问题。因此,在使用 MyBatis 缓存时,需要根据具体的应用场景和数据量进行合理的配置和调优。

2 一级缓存

        一级缓存 (local cache),即本地缓存,作用域默认为 SqlSession 。本地缓存不能被关闭,当 SqlSession flush(插入、更新、修改) 或 close 后,该 SqlSession 中的所有 Cache 将被清空。此外,也可以调用 sqlSession.clearCache() 来手动清空本地缓存。

        在 MyBatis 配置文件中可以通过设置 localCacheScope 参数来改变一级缓存的作用域,它有以下两种设置:

  • SESSION: 当设置为 SESSION 时,一级缓存将对整个 SqlSession 有效。这意味着在同一个 SqlSession 中执行的查询会共享同一个缓存。只有当执行 DML 语句(如插入、更新或删除操作)时,缓存才会被清除。这可以有效地提高相同数据多次查询的速度,但如果在多个 SqlSession 之间需要同步数据,或者有写操作发生,可能会出现脏读的情况
  • STATEMENT:当设置为 STATEMENT 时,一级缓存仅对当前执行的语句有效。这意味着每次语句执行完毕后,缓存就会被清空。这种设置适用于那些可能需要避免脏读风险的场景,因为它确保了每次查询都是独立的,不会受到其他查询的影响
@Test
public void selectById1() {EmployeeMapper mapper = sqlSessionOne.getMapper(EmployeeMapper.class);// 第一次查询System.out.println("第一次查询");Employee employee1 = mapper.selectEmployeeById(1);System.out.println(employee1);// 第二次查询System.out.println("第二次查询");Employee employee2 = mapper.selectEmployeeById(1);System.out.println(employee2);// 手动清除本地缓存System.out.println("清除本地缓存");sqlSessionOne.clearCache();// 第三次查询System.out.println("第三次查询");Employee employee3 = mapper.selectEmployeeById(1);System.out.println(employee3);}

第一次查询,从数据库中查询数据并将查询结果保存在本地缓存中

第二次查询,直接获取本地缓存的查询结果

清空本地缓存

第三次查询,从数据库中查询数据

3 二级缓存

3.1 二级缓存介绍

        MyBatis 的二级缓存是一个更为全局的缓存机制,其作用范围是 namespace 级别,可以被多个 SqlSession 共享。它的生命周期与应用程序同步,主要用于解决一级缓存不能跨会话共享的问题。

以下是二级缓存的一些详细介绍:

  • 使用场景:二级缓存适用于多个 SqlSession 需要共享数据的场景。当开启二级缓存后,MyBatis 会先从二级缓存中获取数据,如果没有找到,则会继续查找一级缓存,最后才访问数据库
  • 配置条件:要使用二级缓存,需要满足以下条件:
    • 全局性地开启或关闭所有映射器配置文件中已配置的任何二级缓存,可以在 MyBatis 配置文件中通过设置 <setting name="cacheEnabled" value="true"> 来实现
    • 在需要使用二级缓存的映射器配置文件(如 sqlMapper.xml)中添加 <cache/> 配置
    • 使用二级缓存的实体类对象必须是可序列化的,即实现 java.io.Serializable 接口
  • 工作机制:当 SqlSession 对象关闭或提交之后,一级缓存中的数据会被写入到二级缓存当中。这样,即使在不同的 SqlSession 之间,也可以访问到相同的数据集,从而提高了数据访问的效率
  • 缓存策略:二级缓存的回收策略可以通过设置 <cache> 标签的属性来定义,例如 LRU(最近最少使用)策略,用于移除最长时间不被使用的对象

3.2 二级缓存配置

在 MyBatis 配置文件进行设置

<!--开启二级缓存-->
<settings><setting name="cacheEnabled" value="true"/>
</settings>

在 SQL 映射文件中设置 <cache> 标签

在 <cache> 标签中,可以设置多种属性来定义缓存的行为,例如:

  • eviction:指定缓存回收策略,默认是 LRU(最近最少使用)
    • LRU:最近最少使用:移除最长时间不被使用的对象
    • FIFO:先进先出:按对象进入缓存的顺序来移除它们
    • SOFT:软引用:移除基于垃圾回收器状态和软引用规则的对象
    • WEAK:弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象
  • flushInterval:设置缓存刷新间隔,单位为毫秒,默认不清空
  • size:指定二级缓存可以存储的最大对象数量,默认是 1024
  • readOnly:标记缓存是否为只读,默认为 false,即可读可写,这回慢一点,但是安全
  • type:指定缓存的具体实现类型
<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>

注:在 Mapper 接口使用 @CacheNamespace 注解也可以开启二级缓存

实体类实现 java.io.Serializable 接口

3.3 二级缓存测试

@Test
public void selectAll() {// 不同 sqlSession 对同一 mapper 接口进行操作SqlSession sqlSession1 = sqlSessionFactory.openSession();EmployeeMapper mapper1 = sqlSession1.getMapper(EmployeeMapper.class);SqlSession sqlSession2 = sqlSessionFactory.openSession();EmployeeMapper mapper2 = sqlSession2.getMapper(EmployeeMapper.class);// 通过 sqlSession1 进行第一次查询List<Employee> employees1 = mapper1.selectAllEmployee();for (Employee employee : employees1) {System.out.println(employee);}// 当 sqlsession 提交、关闭时,二级缓存会有数据//sqlSession1.commit();sqlSession1.clearCache();sqlSession1.close();// 通过 sqlSession2 进行第二次查询List<Employee> employees2 = mapper2.selectAllEmployee();for (Employee employee : employees2) {System.out.println(employee);}
}

通过 sqlSession1 进行第一次查询,二级缓存没有数据

清空 sqlSession1 的一级缓存

sqlSession1 关闭(二级缓存有查询结果,二级缓存的数据是从一级缓存中来的吗???)

通过 sqlSession2 进行第二次查询,从二级缓存中获得查询结果,二级缓存命中率 0.5

补充:

禁用二级缓存

        可以使用 useCache 属性(这个属性只有 select 有)来禁用二级缓存,默认为 true,即使用二级缓存,当然也可以通过 @Options(useCache=true) 来设置。

清空一级和二级缓存

        flushCache 属性是用来清空一级缓存和二级缓存的。select 中默认为 flushCache=false,insert、delete、update 中默认为 flushCache=true,因为执行数据的增删改 SQL 语句后,数据库与缓存数据可能已经不一致,此时缓存已经不能用了,如果不清空缓存则可能出现脏读的情况。也可以通过 @Options(flushCache=options.FlushCachePolicy.TRUE) 进行设置。

也可以通过实现 cache 接口自定义二级缓存

4 参考文档

尚硅谷文档

mybatis 中文文档 – MyBatis 3 | XML 映射器

Mybatis3详解(十二)----Mybatis缓存 - 唐浩荣 - 博客园 (cnblogs.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/715826.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Git与GitHub:解锁版本控制的魔法盒子

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua&#xff0c;在这里我会分享我的知识和经验。&#x…

cetos7 Docker 安装 gitlab

一、gitlab 简单介绍和安装要求 官方文档&#xff1a;https://docs.gitlab.cn/jh/install/docker.html 1.1、gitlab 介绍 gitLab 是一个用于代码仓库管理系统的开源项目&#xff0c;使用git作为代码管理工具&#xff0c;并在此基础上搭建起来的Web服务平台&#xff0c;通过该平…

(六)Dropout抑制过拟合与超参数的选择--九五小庞

过拟合 即模型在训练集上表现的很好&#xff0c;但是在测试集上效果却很差。也就是说&#xff0c;在已知的数据集合中非常好&#xff0c;再添加一些新数据进来效果就会差很多 欠拟合 即模型在训练集上表现的效果差&#xff0c;没有充分利用数据&#xff0c;预测准确率很低&a…

笨办法学 Python3 第五版(预览)(一)

原文&#xff1a;Learn Python the Hard Way, 5th Edition (Early Release) 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 模块 1&#xff1a;Python 入门 练习 0&#xff1a;准备工作 这个练习没有代码。这只是你完成的练习&#xff0c;让你的计算机运行 Python。…

Unity 游戏设计模式:单例模式

本文由 简悦 SimpRead 转码&#xff0c; 原文地址 mp.weixin.qq.com 单例模式 在 C# 游戏设计中&#xff0c;单例模式是一种常见的设计模式&#xff0c;它的主要目的是确保一个类只有一个实例&#xff0c;并提供一个全局访问点。单例模式在游戏开发中具有以下几个作用&#xf…

Matlab 机器人工具箱 Link类

文章目录 1 Link类1.1 机械臂Link类1.2 构造函数1.3 信息/显示方法1.4 转换方法1.5 操作方法1.6 测试方法1.7 重载操作1.8 属性(读/写)1.9 例子2 Link.Link2.1 创建机器人连杆对象2.2 OPTIONS2.3 注意2.4 旧语法2.5 例子3 Link的其他函数3.1 Link.A3.2 Link.char3.3 Link.displ…

unity学习(44)——选择角色菜单——顺利收到服务器的数据

本节的思路参考自&#xff0c;内容并不相同&#xff1a;13ARPG网络游戏编程实践&#xff08;十三&#xff09;&#xff1a;角色选择UI及创建面板制作&#xff08;四&#xff09;_哔哩哔哩_bilibili 现在的代码写在MessageManager.cs中&#xff0c;函数名UserHandler(是从OnMess…

Revit-二开之创建墙-(6)

Revit API窗间墙 protected override Result OnExecute(ExternalCommandData commandData, ref string message, ElementSet elements) {try{// 获取当前活动的文档

你是否知道Python的列表翻转、排序和多维列表

1.reverse() 表示翻转列表中的元素&#xff0c;不会生成新列表 list1 [2343, 55, 4, 345, 676, 768] list1.reverse() print(list1) # [768, 676, 345, 4, 55, 2343] 2.sort() 对原列表元素进行排序&#xff0c;默认是升序 list1 [2343, 55, 4, 345, 676, 768] list1…

腾讯云幻兽帕鲁服务器在Linux和Windows操作系统上的安全性对比如何?哪个更加安全?

腾讯云幻兽帕鲁服务器在Linux和Windows操作系统上的安全性对比如何&#xff1f; Linux因其资源利用率高、稳定性和安全性较强而受到许多专业用户的青睐。这表明在Linux操作系统上&#xff0c;腾讯云可能会更倾向于提供高安全性的服务环境。然而&#xff0c;并没有直接比较Linu…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的夜视行人检测系统(Python+PySide6界面+训练代码)

摘要&#xff1a;开发高效的夜视行人检测系统对于提升夜间安全和监控效能至关重要。本篇博客详尽介绍了如何利用深度学习技术搭建一个夜视行人检测系统&#xff0c;并提供了完整的实现代码。本系统采用了先进的YOLOv8算法&#xff0c;并与YOLOv7、YOLOv6、YOLOv5进行了性能比较…

嵌入式Linux中GPIO设置的一些基本指令和步骤

一、GPIO的介绍 嵌入式Linux中的GPIO&#xff08;General Purpose Input/Output&#xff0c;通用输入/输出&#xff09;是一种常用的接口&#xff0c;允许开发者直接控制硬件设备的某些引脚&#xff0c;进行诸如LED控制、传感器读取、设备状态监测等任务。 二、设置步骤和示例…

第四十四天| 卡尔网 52. 携带研究材料、518. 零钱兑换 II、377. 组合总和 Ⅳ

01背包问题卡尔网 52. 携带研究材料 题目链接&#xff1a;52 携带研究材料 题干&#xff1a;小明是一位科学家&#xff0c;他需要参加一场重要的国际科学大会&#xff0c;以展示自己的最新研究成果。他需要带一些研究材料&#xff0c;但是他的行李箱空间有限。这些研究材料包括…

centos7安装夜莺

一、前期准备 1.1.关闭防火墙&#xff0c;SELINUX systemctl stop firewalld.service systemctl disable firewalld.service setenforce 0 sed -i "s/SELINUXenforcing/SELINUXdisabled/g" /etc/selinux/config查看状态 systemctl status firewalld systemctl sta…

Vue开发实例(三)项目引入Element-UI

项目引入Element-UI 一、引入Element-UI二、注册组件1、vue2使用element-ui2、vue3使用element-ui 三、使用Element组件1、轻微改造2、验证element是否生效 一、引入Element-UI npm i element-ui --save npm install element-ui -S等待安装完成 二、注册组件 1、vue2使用ele…

【Leetcode每日一题】前缀和(难度⭐)(25)

1. 题目解析 题目链接&#xff1a;DP34 【模板】前缀和 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 核心在于计算题目所给区间数组元素和返回即可。 2. 算法原理 为了提高计算效率&#xff0c;我们可以预先计算出一个「前缀…

在github的README.md中插入视频;在github的README.md中添加gif演示动画

最近需要再github中上传项目的源代码&#xff0c;应导师的要求&#xff0c;需要再README中加入对实验视频的展示&#xff0c;但是github的README.md其实就是一个markdown文件&#xff0c;据我的理解这个文件里应该无法直接插入视频吧&#xff1f;&#xff08;如果后续有办法直接…

UE4c++ ConvertActorsToStaticMesh ConvertProceduralMeshToStaticMesh

UE4c ConvertActorsToStaticMesh 创建Edior模块&#xff08;最好是放Editor模块毕竟是编辑器代码&#xff09;创建蓝图函数UBlueprintFunctionLibraryUTestFunctionLibrary.hUTestFunctionLibrary.cpp:.Build.cs 目标:为了大量生成模型&#xff0c;我们把虚幻带有的方法迁移成函…

leetcode 热题 100_三数之和

题解一&#xff1a; 双指针遍历&#xff1a;暴力解法的三层遍历会超时&#xff0c;因此需要优化遍历的过程。首先是需要对结果进行去重&#xff0c;这里采用排序跳过重复值的做法&#xff0c;在指针遍历时跳过已经遍历过的相同值。在第一层循环确定第一个值后&#xff0c;剩下两…

模型部署 - onnx 的导出和分析 -(1) - PyTorch 导出 ONNX - 学习记录

onnx 的导出和分析 一、PyTorch 导出 ONNX 的方法1.1、一个简单的例子 -- 将线性模型转成 onnx1.2、导出多个输出头的模型1.3、导出含有动态维度的模型 二、pytorch 导出 onnx 不成功的时候如何解决2.1、修改 opset 的版本2.2、替换 pytorch 中的算子组合2.3、在 pytorch 登记&…