当前位置: 首页 > news >正文

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都有自己的本地缓存,无法共享缓存数据。

  • 手动清空缓存:通过调用SqlSessionclearCache()方法可以手动清空一级缓存。这样会导致之前缓存的数据被清除,下一次查询会重新从数据库中获取数据。

  • 更新操作:当执行了插入、更新或删除操作时,可能会影响到缓存中的数据。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的缓存实现原理主要基于三级缓存机制&#xff0c;包括一级缓存&#xff08;本地缓存&#xff09;、二级缓存&#xff08;全局缓存&#xff09;和三级缓存&#xff08;跨会话缓存&#xff09;。这个缓存在我们实际开发中可以避免我们查询重复的数据&#xff0c;在一定程度…...

K-means聚类模型

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

免费分享一套微信小程序旅游推荐(智慧旅游)系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】,帅呆了~~

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

Matlab 2023b学习笔记1——界面认识

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

C++ sort排序的总和应用题

第1题 sort排序1 时限&#xff1a;1s 空间&#xff1a;256m 输入n个数&#xff0c;将这n个数从小到大排序&#xff0c;输出。 输入格式 第1行&#xff0c;一个正整数n&#xff08;n<100&#xff09; 第2行&#xff0c;n个正整数&#xff0c;小于100 输出格式 n个整…...

[力扣]——231.2的幂

题目描述&#xff1a; 给你一个整数 n&#xff0c;请你判断该整数是否是 2 的幂次方。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 如果存在一个整数 x 使得 n 2x &#xff0c;则认为 n 是 2 的幂次方。 bool isPowerOfTwo(int n){ if(n0)retur…...

【css】引入背景图时候,路径写入@会报错

看报错信息 我的写法 解决办法 在前面加个~...

【有手就行】使用你自己的声音做语音合成,CPU都能跑,亲测有效

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

《ESP8266通信指南》番外-(附完整代码)ESP8266获取DHT11接入(基于Lua)

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

[IMX6ULL驱动开发]-Linux对中断的处理(一)

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

PHP基础学习笔记(面向对象OOP)

类和对象 <?php //声明一个名为 Fruit 的类&#xff0c;它包含两个属性&#xff08;$name 和 $color&#xff09;以及两个用于设置和获取 $name 属性的方法 set_name() 和 get_name()&#xff1a; class Fruit {// Propertiespublic $name;public $color;// Methodsfuncti…...

Mysql超详细安装配置教程(保姆级图文)

MySQL是一种流行的开源关系型数据库管理系统&#xff0c;它广泛用于网站和服务的数据存储和管理。MySQL以其高性能、可靠性和易用性而闻名&#xff0c;是许多Web应用程序的首选数据库解决方案之一。 一、下载安装包 &#xff08;1&#xff09;从网盘下载安装文件 点击此处直…...

HR招聘测评,如何判断候选人的团队协作能力?

什么是团队协作能力&#xff1f; 团队协作能力&#xff0c;说的是在集体环境中&#xff0c;能同他人协同工作&#xff0c;为追求共同的目标而努力&#xff0c;其中包括沟通&#xff0c;表达&#xff0c;协调&#xff0c;尊重&#xff0c;信任&#xff0c;责任共担等一系列综合…...

[STM32-HAL库]Flash库-HAL库-复杂数据读写-STM32CUBEMX开发-HAL库开发系列-主控STM32F103C6T6

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

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&#xff08;Remote Terminal Unit&#xff09;是一种串行通信协议&#xff0…...

【Qt】如何优雅的进行界面布局

文章目录 1 :peach:写在前面:peach:2 :peach:垂直布局:peach:3 :peach:水平布局:peach:4 :peach:网格布局:peach:5 :peach:表单布局:peach: 1 &#x1f351;写在前面&#x1f351; 之前使⽤ 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 中&#xff0c;事件循环由 libuv 库…...

关于基础的流量分析(1)

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

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

LLMs 系列实操科普(1)

写在前面&#xff1a; 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容&#xff0c;原视频时长 ~130 分钟&#xff0c;以实操演示主流的一些 LLMs 的使用&#xff0c;由于涉及到实操&#xff0c;实际上并不适合以文字整理&#xff0c;但还是决定尽量整理一份笔…...

探索Selenium:自动化测试的神奇钥匙

目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...