Mybatis缓存测试

实体类

Student

@Data
@Table(name = "student")
public class StudentEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

    @Column(name = "class_id")
    private Long classId;
    
    @Transient
    private String className;

}

Class

@Data
@Table(name = "class")
public class ClassEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

}

表结构

CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `class_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
CREATE TABLE `class` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

一级缓存

一级缓存是sqlSession级别的,二级缓存是SqlSessionFactory级别的

一级缓存-测试1

   @Autowired
   private SqlSessionFactory sqlSessionFactory;

   @Test
   public void t1() {
       SqlSession sqlSession = sqlSessionFactory.openSession();
       // 同一个sqlSession,同一个mapper实例,执行相同的查询语句
       StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);

       studentMapper.selectAll();
       studentMapper.selectAll();
       // 结论:只会出现1次sql语句,第二次查询走缓存
   }

在这里插入图片描述

一级缓存-测试2

   @Test
   public void t2() {
       SqlSession sqlSession = sqlSessionFactory.openSession();
       // 同一个sqlSession,不同的mapper实例,执行相同的查询语句
       StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
       studentMapper.selectAll();

       StudentMapper studentMapper2 = sqlSession.getMapper(StudentMapper.class);
       studentMapper2.selectAll();
       // 结论:只会出现1次sql语句,第二次查询走缓存
   }

在这里插入图片描述

一级缓存-测试3

   @Test
   public void t3() {
       // 不同sqlSession,执行相同的查询语句
       SqlSession sqlSession = sqlSessionFactory.openSession();
       SqlSession sqlSession2 = sqlSessionFactory.openSession();

       StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
       studentMapper.selectAll();

       StudentMapper studentMapper2 = sqlSession2.getMapper(StudentMapper.class);
       studentMapper2.selectAll();
       // 结论:出现2次sql语句,没有缓存效果
   }

在这里插入图片描述

一级缓存-测试4(update)

   @Test
   public void t4() {
       SqlSession sqlSession = sqlSessionFactory.openSession();

       // 第一次查询
       StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
       List<StudentEntity> list = studentMapper.selectAll();

       // 更新操作
       StudentEntity student = list.get(0);
       student.setName("修改学生姓名");
       studentMapper.updateByPrimaryKey(student);

       // 第二次查询
       studentMapper.selectAll();
       // 结论:第一次会出现sql语句,由于进行了更新操作,导致缓存失效,第二次查询也会重新查询sql
   }

在这里插入图片描述

一级缓存-测试5(update)

和测试4类似,但是update的对象改为class,看看是否会影响student的查询

   @Test
   public void t5() {
       SqlSession sqlSession = sqlSessionFactory.openSession();

       // 第一次查询student
       StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
       List<StudentEntity> list = studentMapper.selectAll();

       // 更新class
       ClassMapper classMapper = sqlSession.getMapper(ClassMapper.class);
       ClassEntity classx = classMapper.selectAll().get(0);
       classx.setName("修改班级姓名");
       classMapper.updateByPrimaryKey(classx);

       // 第二次查询student
       studentMapper.selectAll();
       // 结论:第一次会出现sql语句,由于进行了更新操作(即使不是同一个mapper实例),也会导致缓存失效,第二次查询也会重新查询sql
   }

在这里插入图片描述

一级缓存-测试6(springboot失效)

   @Autowired
   private StudentMapper studentMapper;
   
   @Test
   public void t6() {

       // 使用mybatis整合springboot后,直接查询2次
       studentMapper.selectAll();
       studentMapper.selectAll();

       // 结论:会出现2次sql查询,缓存失效,因为每一次sql语句的执行都是使用新的sqlSession
   }

在这里插入图片描述

二级缓存

一级缓存默认开启,二级缓存默认关闭

开启配置

mybatis:
  configuration:
    cache-enabled: true

给mapper添加<cache/>,前面用的通用mapper的selectAll方法,二级缓存一直没生效,这里重新手写一个查询方法getAll,再加上useCache配置才行

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.tw.nr.network.dao.mapper.StudentMapper">

	<cache/><!--开启二级缓存-->
	
	<!--获取学生列表-->
	<select id="getAll" resultType="com.tw.nr.network.entity.StudentEntity" useCache="true">
		select * from student;
	</select>

	<!--获取学生详细信息-->
	<select id="getStudentDetail" resultType="com.tw.nr.network.entity.StudentEntity" useCache="true">
		SELECT
			a.`name`,
			b.`name` AS className
		FROM
			student a
			JOIN class b ON a.class_id = b.id
		where
		    a.id=#{id}
	</select>

</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.tw.nr.network.dao.mapper.ClassMapper">

    <cache/><!--开启二级缓存-->

</mapper>

二级缓存-测试1

   @Test
   public void t7() {

       // 不同sqlSession,执行相同的查询语句
       SqlSession sqlSession = sqlSessionFactory.openSession();
       SqlSession sqlSession2 = sqlSessionFactory.openSession();

       StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
       studentMapper.getAll();
       sqlSession.commit();

       StudentMapper studentMapper2 = sqlSession2.getMapper(StudentMapper.class);
       studentMapper2.getAll();
       
       // 结论:只会查询1次sql语句,第二次查询走缓存
   }

在这里插入图片描述

二级缓存-测试2(脏数据)

二级缓存不适合多表查询,因为studentclass处于不同的命名空间,在student的命名空间执行了sqlA的联表查询(student和class联表),进行了缓存,然后class执行了更新,但这并不会刷新sqlA的缓存,导致sqlA还是读取到了脏数据

   @Test
   public void t8() {

       SqlSession sqlSession = sqlSessionFactory.openSession();

       // 第一次查询学生的详细信息(联查了class表)
       StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
       StudentEntity student = studentMapper.getStudentDetail(1L);
       System.out.println(student);
       sqlSession.commit();

       // 更新了class表
       ClassMapper classMapper = sqlSession.getMapper(ClassMapper.class);
       ClassEntity classx = classMapper.selectAll().get(0);
       classx.setName("班级1000");
       classMapper.updateByPrimaryKey(classx);
       sqlSession.commit();

       // 再次查询学生的详细信息
       student = studentMapper.getStudentDetail(1L);
       System.out.println(student);

       /**
        * 结论:读取到了脏数据,二级缓存不适合多表查询,因为student和class处于不同的命名空间,在student的命名空间执行了sqlA的联表查询(student和class联表),进行了缓存
        * 然后class执行了更新,但这并不会刷新sqlA的缓存,导致sqlA还是读取到了脏数据
        * */
   }

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络爬虫设置代理服务器

目录 1&#xff0e;获取代理 IP 2&#xff0e;设置代理 IP 3. 检测代理 IP 的有效性 4. 处理异常 如果希望在网络爬虫程序中使用代理服务器&#xff0c;就需要为网络爬虫程序设置代理服务器。 设置代理服务器一般分为获取代理 IP 、设置代理 IP 两步。接下来&#xff0c;分…

【STM32--Cortex-M3】

STM32-Cortex-M3 ■ Cortex-M3 处理器内核到基于Cortex-M3的MCU■ ARM的各种架构版本■ 指令集■ Cortex-M3简介■ Cortex-M3寄存器组■ Cortex-M3■ Cortex-M3■ Cortex-M3 ■ Cortex-M3 处理器内核到基于Cortex-M3的MCU Cortex-M3处理器内核是单片机的中央处理单元&#xff…

JDK18特性

JDK18特性 一、JAVA18概述 Java 18 在 2022 年 3 月 22 日正式发布,Java 18 不是一个长期支持版本,这次更新共带来 9 个新功能。 https://openjdk.org/projects/jdk/18/ 二、具体新特性 1. 默认UTF-8字符编码 JDK 一直都是支持 UTF-8 字符编码,这次是把 UTF-8 设置为了默…

RPM 打包入门(基于openEuler)

主要参考内容&#xff08;均为官方文档&#xff09;&#xff1a; https://rpm-packaging-guide.github.io/#building-rpms https://docs.redhat.com/zh_hans/documentation/red_hat_enterprise_linux/8/html/packaging_and_distributing_software/introduction-to-rpm_packagin…

Opencv学习项目5——pyzbar,numpy

上一次我们使用pyzbar进行解码二维码并将其内容显示在图像上&#xff0c;使用的是rect barcode.rect来获取图像的坐标&#xff0c;这次我们使用另一种方法来获取坐标进行画框。 Numpy介绍 NumPy 是一个用于科学计算的开源 Python 库&#xff0c;提供了对大量数值数据进行高效操…

Java学习笔记(一)Java内容介绍、程序举例、DOS命令、Java跨平台特性的本质

Hi i,m JinXiang ⭐ 前言 ⭐ 本篇文章主要介绍Java内容介绍、程序举例、DOS命令、Java跨平台特性的本质详细介绍以及部分理论知识 🍉欢迎点赞 👍 收藏 ⭐留言评论 📝私信必回哟😁 🍉博主收将持续更新学习记录获,友友们有任何问题可以在评论区留言 目录 1、内容介绍…

STM32项目分享:家庭环境监测系统

目录 一、前言 二、项目简介 1.功能详解 2.主要器件 三、原理图设计 四、PCB硬件设计 1.PCB图 2.PCB板打样焊接图 五、程序设计 六、实验效果 七、资料内容 项目分享 一、前言 项目成品图片&#xff1a; 哔哩哔哩视频链接&#xff1a; https://www.bilibili.…

数据可视化实验四:Pyecharts数据可视化

目录 一、使用PyEcharts绘制全国肺炎确诊人数分布图 1.1 柱状图 1.1.2 代码实现 1.1.2 绘制结果 1.2 饼状图 1.2.1 代码实现 1.2.2 绘制结果 1.3 使用over lap实现图形叠加 1.3.1 代码实现 1.3.2 绘制结果 1.4 地图绘制-Map 1.4.1 代码实现 1.4.2 绘制结果 1.5 地…

ECharts 词云图案例二:创意蒙版应用

ECharts 词云图案例二&#xff1a;创意蒙版应用 引言 在数据可视化领域&#xff0c;ECharts 以其强大的功能性和灵活性&#xff0c;成为开发者和设计师的首选工具之一。继上一篇关于 ECharts 词云图的详细介绍后&#xff0c;本文将探索词云图的进阶应用——使用蒙版来创造更具…

谷歌手机刷机教学

注意&#xff1a;手机已经解开了oem锁和bl 1、adb基础命令 连接设备adb devices&#xff1a;列出当前连接的所有设备。 adb connect <设备IP>&#xff1a;通过IP地址连接设备&#xff08;用于无线连接&#xff09;。 设备信息adb shell getprop&#xff1a;获取设备的所…

MySQL的DDL语句

文章目录 ☃️概述☃️DDL&#xff08;数据定义语言&#xff09;☃️数据库操作☃️表操作☃️DDL的重要性 ☃️概述 MySQL 通用语法分类 ● DDL: 数据定义语言&#xff0c;用来 定义数据库对象&#xff08;数据库、表、字段&#xff09; ● DML: 数据操作语言&#xff0c;用…

C#修改 EXE 文件图标和 winForm 窗口图标

修改 EXE 文件图标 1.准备好图片&#xff0c;转换为 Icon 图片&#xff1b; 2.右键工程&#xff0c;选择属性&#xff1b; 3.选择 Icon 图标即可&#xff1b; 4.重新生成可执行文件&#xff0c;查看。 修改 winForm 窗口图标 1.选中 winForm &#xff0c;查看属性&#x…

Android提供的LruCache类简介(1)

* If your cached values hold resources that need to be explicitly released, * override {link #entryRemoved}. * 如果你cache的某个值需要明确释放&#xff0c;重写entryRemoved() * If a cache miss should be computed on demand for the corresponding keys, * ov…

CVPR最佳论文:谷歌基于Spectral Volume从单图生成视频

一、摘要&#xff1a; 论文&#xff1a;Generative Image Dynamics&#xff0c;https://arxiv.org/pdf/2309.07906 项目主页&#xff1a;https://generative-dynamics.github.io/ 本文提出了一种新颖的方法来模拟场景运动的图像空间先验。通过从真实视频序列中提取的自然振荡…

调试实战 | 记一次有教益的 vs2022 内存分配失败崩溃分析(续)

前言 前一阵子遇到了 vs2022 卡死的问题&#xff0c;在上一篇文章中重点分析了崩溃的原因 —— 当 vs2022 尝试分配 923MB 的内存时&#xff0c;物理内存页文件大小不足以满足这次分配请求&#xff0c;于是抛出异常。 本篇文章将重点挖掘一下 vs2022 在崩溃之前已经分配的内容…

昇思25天学习打卡营第4天|网络构建|函数式自动微分

学AI还能赢奖品&#xff1f;每天30分钟&#xff0c;25天打通AI任督二脉 (qq.com) 网络构建 神经网络模型是由神经网络层和Tensor操作构成的&#xff0c;mindspore.nn提供了常见神经网络层的实现&#xff0c;在MindSpore中&#xff0c;Cell类是构建所有网络的基类&#xff0c;也…

借助AI营销类API,实现自动化的营销流程

借助AI营销类API&#xff0c;企业可以实现自动化的营销流程&#xff0c;提高效率和效果&#xff0c;并节省大量的时间和资源。这些API利用人工智能和机器学习的技术&#xff0c;能够自动化地执行各种营销任务和流程。首先&#xff0c;AI营销类API可以帮助企业实现自动化的市场调…

【鸿蒙】创建第⼀个鸿蒙项⽬

点击 Create Project 配置项目 开发工具界面 工程介绍

探索AI前沿:本地部署GPT-4o,打造专属智能助手!

目录 1、获取API_key 2、开始调用 3、openai连接异常 4、解决方法&#xff1a; 5、调用GPT-4o 1、获取API_key 这里就不多赘述了&#xff0c;大家可以参考下面这篇博客 怎么获取OpenAI的api-key【人工智能】https://blog.csdn.net/qq_51625007/article/details/13763274…

大数据与java哪个好找工作?这篇文章帮你做选择!

大数据与java哪个好找工作&#xff1f;这篇文章帮你做选择&#xff01; 还在为选择Java开发还是Java大数据而头疼吗&#xff1f;别担心&#xff0c;本文将从就业前景、学习方向、学习内容以及薪资待遇四个方面&#xff0c;为你揭开Java和Java大数据的神秘面纱&#xff0c;帮你做…