MyBatis系统学习篇 - MyBatis的缓存
MyBatis的缓存实现原理主要基于三级缓存机制,包括一级缓存(本地缓存)、二级缓存(全局缓存)和三级缓存(跨会话缓存)。这个缓存在我们实际开发中可以避免我们查询重复的数据,在一定程度上可以帮助我们减少对数据库同一数据的重复查询,也可以在一定程度上使用MyBatis缓存可以帮助我们更好的查询数据和进行数据交互,减少对数据库的数据查询次数吧。
一级缓存
MyBatis一级缓存也可以称作本地缓存,他是SqlSession级别的缓存,默认开启,可以减少我们对数据库的重复查询,当执行查询的时候,查询结果会被存储在SqlSession中的本地存储中,在同一个Session中,如果执行相同的查询,MyBatis会从本地缓存中查找结果,如果找到则直接返回,否则再去数据库中查询并存储到本地缓存中。
一级缓存的实现
// 在MyBatis配置文件中开启一级缓存
<configuration><settings><setting name="localCacheScope" value="SESSION"/></settings>
</configuration>
public static void main(String[] args) {try (SqlSession sqlSession = sqlSessionFactory.openSession()) {EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);// 测试一级缓存Emp emp1 = empMapper.getEmpById(1); // 第一次查询,会从数据库中获取数据Emp emp2 = empMapper.getEmpById(1); // 第二次查询,会从一级缓存中获取数据System.out.println(emp1 == emp2); // 输出:true,说明从一级缓存中获取到了同一个对象}}
一级缓存失效的几种情况:
-
不同的SqlSession:一级缓存是基于
SqlSession
的,当使用不同的SqlSession
对象执行相同的查询时,一级缓存会失效。因为每个SqlSession
都有自己的本地缓存,无法共享缓存数据。 -
手动清空缓存:通过调用
SqlSession
的clearCache()
方法可以手动清空一级缓存。这样会导致之前缓存的数据被清除,下一次查询会重新从数据库中获取数据。 -
更新操作:当执行了插入、更新或删除操作时,可能会影响到缓存中的数据。MyBatis会自动将更新操作同步到缓存中,但是会清空相关的缓存数据,以保证缓存的数据与数据库的数据一致。
-
缓存大小限制:一级缓存的大小是有限的,默认情况下,一级缓存的大小为1024个对象。当缓存中的对象数量达到上限时,新的查询结果会导致最早的查询结果被淘汰出缓存,从而失效。
-
手动提交事务:如果在执行查询之前手动提交了事务(调用了
commit()
方法),则会导致一级缓存失效。因为事务提交后,会关闭当前的SqlSession
,同时清空一级缓存。
二级缓存
MyBatis二级缓存也可以被称作全局缓存,一般上是默认关闭的,并且配置方式也与一级缓存有区别,需要我们在具体的mapper映射文件中手动配置开启。
二级缓存开启的条件:
因为二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果被缓存,伺候再次执行相同的查询语句就可以直接从缓存中获取。
- 在核心配置文件中,设置全局配置属性
cacheEnable="true"
,默认true,一般不需要设置- 在映射文件中配置
<cache />
- 二级缓存必须在SqlSession关闭或者提交后有效
- 查询的数据所转换的实体类类型必须实现序列化的接口。
当我们开启二级缓存的时候,查询的结果会被存储在Mapper的全局缓存中,多个SqlSession可以共享同一个Mapper的二级缓存,在执行查询的时候,MyBatis会从我们的二级缓存中查询结果,如果找到则直接返回,如果没有找到,那么就会去数据库中查询,并存储到二级缓存中。
// 在Mapper接口对应的映射文件中开启二级缓存
<cache/>
public static void main(String[] args) {try (SqlSession sqlSession = sqlSessionFactory.openSession()) {EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);// 测试二级缓存SqlSession sqlSession2 = sqlSessionFactory.openSession();EmpMapper empMapper2 = sqlSession2.getMapper(EmpMapper.class);Emp emp3 = empMapper2.getEmpById(1); // 第一次查询,会从数据库中获取数据sqlSession2.close(); // 关闭SqlSessionSqlSession sqlSession3 = sqlSessionFactory.openSession();EmpMapper empMapper3 = sqlSession3.getMapper(EmpMapper.class);Emp emp4 = empMapper3.getEmpById(1); // 第二次查询,会从二级缓存中获取数据sqlSession3.close();System.out.println(emp3 == emp4); // 输出:true,说明从二级缓存中获取到了同一个对象}}
cache标签的配置属性值
-
eviction
:指定缓存的回收策略,用于决定在缓存达到上限时如何清理缓存。常用的回收策略包括:LRU
(Least Recently Used):最近最少使用,根据最近的访问时间来淘汰数据。FIFO
(First In, First Out):先进先出,根据数据最早进入缓存的时间来淘汰数据。SOFT
:软引用,根据JVM的垃圾回收机制来决定是否清理缓存数据。WEAK
:弱引用,类似于软引用,但更容易被垃圾回收器回收。
-
flushInterval
:指定缓存刷新间隔,表示缓存刷新的时间间隔,单位为毫秒。设置了该属性后,缓存会定期刷新,以保证缓存数据的有效性。 -
readOnly
:指定缓存是否为只读,如果设置为true,表示缓存数据不会被修改,可以提高缓存的性能。 -
size
:指定缓存的大小限制,表示缓存中可以存储的对象数量上限。当缓存中的对象数量达到该上限时,会根据回收策略进行数据清理。 -
type
:指定缓存的实现类型,可以是MyBatis提供的内置缓存实现,也可以是自定义的缓存实现。常用的内置缓存实现包括:PERPETUAL
:永久缓存,数据永久保存在缓存中。FIFO
:先进先出缓存。LRU
:最近最少使用缓存。SOFT
:软引用缓存。WEAK
:弱引用缓存。
示例配置:
<cacheeviction="LRU"flushInterval="60000"readOnly="false"size="1024"type="PERPETUAL"/>
MyBatis缓存查询顺序:
先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿出来使用,如果二级缓存没有命中,那就在查一级缓存,如果一级缓存也没有命中,那就查询数据库。SqlSession关闭后,以及缓存中的数据会写入到二级缓存中。
二级缓存失效的几种原因:
数据更新:当执行了插入、更新或删除操作时,会导致与这些操作相关的缓存数据失效。MyBatis会自动将更新操作同步到缓存中,但也会清空相关的缓存数据,以保证缓存中的数据与数据库的数据一致。
并发操作:在并发环境下,如果多个线程同时对同一条数据进行更新操作,可能会导致缓存中的数据与数据库中的数据不一致。这时需要考虑缓存的并发控制策略,以避免脏数据的产生。
查询结果不满足缓存条件:MyBatis的二级缓存对查询结果有一定的条件限制,例如查询结果的类型必须是可序列化的、不能包含动态SQL等。如果查询结果不满足这些条件,可能会导致缓存失效。
缓存大小限制:二级缓存的大小是有限的,当缓存中的对象数量达到上限时,新的查询结果会导致最早的查询结果被淘汰出缓存,从而失效。
手动清空缓存:通过调用SqlSession的clearCache()方法可以手动清空二级缓存。这样会导致之前缓存的数据被清除,下一次查询会重新从数据库中获取数据。
事务提交:如果在执行查询之前手动提交了事务(调用了commit()方法),则会导致二级缓存失效。因为事务提交后,会关闭当前的SqlSession,同时清空二级缓存。
三级缓存
三级缓存是一种跨会话级别的缓存,他通过与外部缓存系统,例如Redis,Memcached等进行实现。通过外部缓存系统的集成,进而实现多个应用实例之间的缓存共享,从而提高缓存的利用率和拓展性。
关于三级缓存,无法依靠MyBatis单独实现,因为他本事不提供直接对外缓存系统的集成,故而无法实现一个完整的三级缓存示例,然而,可以通过MyBatis的扩展插件或者自定义实现来集成外部缓存系统,例如:Redis,Memcached等。
我们采用Redis自定义实现Mybatis的三级缓存。
首先,需要引入MyBatis的扩展插件,例如MyBatis Redis Cache,它是一个MyBatis的缓存插件,可以将缓存数据存储到Redis中。
然后,需要在MyBatis的配置文件中配置该插件,指定Redis作为缓存的实现:
<configuration><settings><setting name="cacheEnabled" value="true"/></settings><typeAliases><!-- 定义需要缓存的实体类别名 --></typeAliases><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><!-- 配置数据源信息 --></dataSource></environment></environments><mappers><!-- 配置Mapper接口 --></mappers><plugins><plugin interceptor="org.mybatis.caches.redis.RedisCache"/></plugins>
</configuration>
<plugin>
标签配置了MyBatis Redis Cache插件,将Redis作为缓存的实现。
接下来,可以在Java代码中进行测试,通过调用Mapper接口的方法来触发缓存的使用:
public class MyBatisCacheTest {public static void main(String[] args) {try (SqlSession sqlSession = sqlSessionFactory.openSession()) {EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);// 调用Mapper接口的方法进行查询Emp emp1 = empMapper.getEmpById(1); // 第一次查询,会从数据库中获取数据Emp emp2 = empMapper.getEmpById(1); // 第二次查询,会从Redis缓存中获取数据System.out.println(emp1 == emp2); // 输出:true,说明从Redis缓存中获取到了同一个对象}}
}
实际的三级缓存实现可能会更加复杂,涉及到缓存的清理、失效策略、缓存击穿和雪崩等问题,需要根据实际情况进行更加细致的配置和测试。
相关文章:

MyBatis系统学习篇 - MyBatis的缓存
MyBatis的缓存实现原理主要基于三级缓存机制,包括一级缓存(本地缓存)、二级缓存(全局缓存)和三级缓存(跨会话缓存)。这个缓存在我们实际开发中可以避免我们查询重复的数据,在一定程度…...

K-means聚类模型
目录 1.定义 2.K-means聚类模型的优点 3.K-means聚类模型的缺点 4.K-means聚类模型的应用场景 5.对K-means聚类模型未来的展望 6.小结 1.定义 什么是 K-means 聚类模型?K-means 聚类模型是一种无监督学习算法,用于将数据划分为不同的组或簇&#…...

免费分享一套微信小程序旅游推荐(智慧旅游)系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】,帅呆了~~
大家好,我是java1234_小锋老师,看到一个不错的微信小程序旅游推荐(智慧旅游)系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序旅游推荐(智慧旅游)系统(SpringBoot后端Vue管理端) Java毕业设计…...

Matlab 2023b学习笔记1——界面认识
下载安装好Matlab后,可以看到如下界面: 可以看到,这时只有命令行窗口。我们在上方工具栏中选择“布局”—— “默认”,即可看到左右两边多出来了“当前文件夹”与“工作区”两栏。 一、当前文件夹界面 这个界面显示的是当前目录下…...

C++ sort排序的总和应用题
第1题 sort排序1 时限:1s 空间:256m 输入n个数,将这n个数从小到大排序,输出。 输入格式 第1行,一个正整数n(n<100) 第2行,n个正整数,小于100 输出格式 n个整…...

[力扣]——231.2的幂
题目描述: 给你一个整数 n,请你判断该整数是否是 2 的幂次方。如果是,返回 true ;否则,返回 false 。 如果存在一个整数 x 使得 n 2x ,则认为 n 是 2 的幂次方。 bool isPowerOfTwo(int n){ if(n0)retur…...

【css】引入背景图时候,路径写入@会报错
看报错信息 我的写法 解决办法 在前面加个~...

【有手就行】使用你自己的声音做语音合成,CPU都能跑,亲测有效
此文介绍在百度飞桨上一个公开的案例,亲测有效。 厌倦了前篇一律的TTS音色了吗?打开短视频听来听去就是那几个声音,快来试试使用你自己的声音来做语音合成吧!本教程非常简单,只需要你能够上传自己的音频数据就可以(建议…...

《ESP8266通信指南》番外-(附完整代码)ESP8266获取DHT11接入(基于Lua)
前言 此篇为番外篇,是 ESP8266 入门的其他功能教程,包括但不限于 DHT11 驱动TCP 通信Thingsboard 平台的接入阿里云物联网云平台接入华为云平台接入 1. 小节目标 使用 Lua 驱动 DHT11 传感器,获取温湿度的值 2. 进入主题 NodeMCU 基于 LUA 相关资料 官方文档:…...

[IMX6ULL驱动开发]-Linux对中断的处理(一)
目录 中断概念的引入 ARM架构中断的流程 异常向量表 Linux系统对中断的处理 ARM对程序和中断的处理 Linux进程中断处理 中断概念的引入 如何理解中断,我们可以进行如下抽象。把CPU看做一个母亲,当它正在执行任务的时候,可以看为是一个母…...

PHP基础学习笔记(面向对象OOP)
类和对象 <?php //声明一个名为 Fruit 的类,它包含两个属性($name 和 $color)以及两个用于设置和获取 $name 属性的方法 set_name() 和 get_name(): class Fruit {// Propertiespublic $name;public $color;// Methodsfuncti…...

Mysql超详细安装配置教程(保姆级图文)
MySQL是一种流行的开源关系型数据库管理系统,它广泛用于网站和服务的数据存储和管理。MySQL以其高性能、可靠性和易用性而闻名,是许多Web应用程序的首选数据库解决方案之一。 一、下载安装包 (1)从网盘下载安装文件 点击此处直…...

HR招聘测评,如何判断候选人的团队协作能力?
什么是团队协作能力? 团队协作能力,说的是在集体环境中,能同他人协同工作,为追求共同的目标而努力,其中包括沟通,表达,协调,尊重,信任,责任共担等一系列综合…...

[STM32-HAL库]Flash库-HAL库-复杂数据读写-STM32CUBEMX开发-HAL库开发系列-主控STM32F103C6T6
目录 一、前言 二、实现步骤 1.STM32CUBEMX配置 2.导入Flash库 3.分析地址范围 4.找到可用的地址 5.写入读取普通数据 6.写入读取字符串 6.1 存储相关信息 6.2 存取多个参数 三、总结及源码 一、前言 在面对需要持久化存储的数据时,除了挂载TF卡,我们…...

windows 下访问 csdn 异常问题
windows下访问csdn可能会出现什么 确认是真人 或着直接连接不上的情况, 需要在 C:\Windows\System32\drivers\etc 路径下 hosts文件中添加如下内容 1.180.18.85 blog.csdn.net 如果目录下没有hosts文件就自己建一个...

vue3结合element-plus之如何优雅的使用表格
背景 表格组件的使用在后台管理系统中是非常常见的,但是如果每次使用表格我们都去一次一次地从 element-plus 官网去 复制、粘贴和修改成自己想要的表格。 这样一来也说得过去,但是如果我们静下来细想不难发现,表格的使用都是大同小异的,每次都去复制粘贴,对于有很多表格…...

网络协议——Modbus-RTU
目录 1、简介 2、消息格式 3、Modbus寄存器种类说明 4、功能码01H 5、功能码02H 6、功能码03H 7、功能码04H 8、功能码05H 9、功能码06H 10、功能码0FH 11、功能码10H 1、简介 Modbus-RTU(Remote Terminal Unit)是一种串行通信协议࿰…...

【Qt】如何优雅的进行界面布局
文章目录 1 :peach:写在前面:peach:2 :peach:垂直布局:peach:3 :peach:水平布局:peach:4 :peach:网格布局:peach:5 :peach:表单布局:peach: 1 🍑写在前面🍑 之前使⽤ Qt 在界⾯上创建的控件, 都是通过 “绝对定位” 的⽅式来设定的。也就是每个控件所在…...

【八股系列】分别说一下nodeJS和浏览器的事件循环机制?
文章目录 1. NodeJS1.1 Node.js 事件循环概念1.2 Node.js 事件循环工作流程1.3 Node.js 事件循环示例 2. 浏览器2.1 浏览器事件循环概念2.2 浏览器事件循环工作流程2.3 浏览器事件循环示例 1. NodeJS 1.1 Node.js 事件循环概念 在 Node.js 中,事件循环由 libuv 库…...

关于基础的流量分析(1)
1.对于流量分析基本认识 1)简介:网络流量分析是指捕捉网络中流动的数据包,并通过查看包内部数据以及进行相关的协议、流量分析、统计等来发现网络运行过程中出现的问题。 2)在我们平时的考核和CTF比赛中,基本每次都有…...

数据结构---树,二叉树的简单概念介绍、堆和堆排序
树 树的概念和结构 结构 在我们将堆之前,我们先来了解一下我们的树。 我们的堆是属于树里面的一种, 树是一种非线性结构,是一种一对多的一种结构,也就是我们的一个节点可能有多个后继节点,当然也可以只有一个或者没…...

MySQL聚合函数(多行函数)
聚合函数(多行函数) 聚合函数作用于一组数据,并对一组数据返回一个值。 常见聚合函数 AVG和SUM函数 只作用于数值类型数据,不包含NULL 求工资平均值和总和 MIN和MAX函数 可以作用于任何数据类型(如字符串,…...

智慧教室课堂-专注度及考试作弊系统、课堂动态点名,情绪识别、表情识别和人脸识别结合
课堂专注度分析: 课堂专注度表情识别 作弊检测: 关键点计算方法 转头(probe)低头(peep)传递物品(passing) 侧面的传递物品识别 逻辑回归关键点 使用: 运行setup.py安装必要内容 python setup.py build develop 运行demo_inference.py 将…...

单例模式简要介绍
学习目标: 单例模式 学习内容: 单例模式(Singleton Pattern)是一种设计模式,其主要目的是确保一个类只有一个实例,并且提供一个全局的访问点。它常用于需要全局唯一对象的场景,例如日志记录器、…...

深度学习面试问题总结(21)| 模型优化
本文给大家带来的百面算法工程师是深度学习模型优化面试总结,文章内总结了常见的提问问题,旨在为广大学子模拟出更贴合实际的面试问答场景。在这篇文章中,我们还将介绍一些常见的深度学习面试问题,并提供参考的回答及其理论基础&a…...

4月手机行业线上市场销售数据分析
政府对智能手机行业的支持政策,如5G推广,以及相关的产业政策,都在一定程度上推动了智能手机市场的发展,再加上AI应用的推广和全球科技迅猛发展,中国手机市场在2024年迎来了恢复性增长。 据鲸参谋数据统计,…...

首都师范大学聘请旅美经济学家向凌云为客座教授
2024年4月17日,首都师范大学客座教授聘任仪式在首都师范大学资源环境与旅游学院举行。首都师范大学资源环境与旅游学院院长吕拉昌主持了仪式,并为旅美经济学家向凌云教授颁发了聘书。 吕拉昌院长指出,要贯彻教育部产学研一体化战略࿰…...

多电脑共享鼠标键盘
由于要在两个电脑之间共用一套鼠标键盘,所以在此记录一下。 mouse without borders Mouse without Borders 是一款免费的 Windows 工具,允许你在多台电脑之间共享鼠标和键盘。 安装与配置步骤 下载和安装: 前往 Mouse without Borders 官…...

展厅设计对企业有哪些作用
1、增强品牌形象 企业展厅对于增强企业品牌形象、提升企业的知名度和市场竞争力具有显著作用和意义。展厅作为企业对外的窗口,是客户和访客了解企业的第一印象。通过独特的设计风格和精心的展示布局,企业可以将自身的核心价值和文化理念巧妙地融入到展厅…...

LeetCode-102. 二叉树的层序遍历【树 广度优先搜索 二叉树】
LeetCode-102. 二叉树的层序遍历【树 广度优先搜索 二叉树】 题目描述:解题思路一:一个全局队列queue,while queue:去搜集当前所有queue的level解题思路二:背诵版解题思路三: 题目描述: 给你二…...