【mybatis】缓存

目录

1. mybatis的运行

1.1 引言

1.2 具体运行: 

1.3 sqlSession

介绍local catch

2. 缓存

2.1 概念

 2.2 使用缓存的原因

2.3 什么样的数据能使用缓存

3.  Mybatis缓存

 3.1 一级缓存

3.1.1 测试一级缓存

3.1.2  缓存失效的四种情况

$1 sqlSession不同

$2  sqlSession相同,查询条件不同

$3  sqlSession相同,两次查询之间执行了增删改操作

$4 sqlSession相同,手动清除一级缓存

3.2 二级缓存

3.2.1 二级缓存开启的条件

3.2.2 二级缓存失效的情况

3.2.3 开启二级缓存

3.2.4 分析 

 3.2.5 重要结论

 3.3 Catch参数的具体细节

4. Mybatis缓存查询顺序


1. mybatis的运行

1.1 引言

        当我们想运行这个selectUser,运行之前有@Before@After, 在执行方法 之前  之后  运行(  init()在执行方法之前执行,selectUser()方法执行,destroy()在执行方法之后执行)。

@Before  //前置通知, 在方法执行之前执行public void init() throws IOException {//加载主配置文件,目的是为了构建SqlSessionFactory对象in = Resources.getResourceAsStream("SqlMapConfig.xml");//创建SqlSessionFactory对象SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);//通过SqlSessionFactory工厂对象创建SqlSesssion对象session = factory.openSession();//通过Session创建UserDao接口代理对象mapper = session.getMapper(UserDao.class);}@After  //@After: 后置通知, 在方法执行之后执行 。public void destory() throws IOException {//释放资源session.close();in.close();}

1.2 具体运行: 

        ①。首先,是sqlMapConfig文件,配置信息,所以第一步,读取sqlMapConfig配置文件

-- sqlMapConfig文件里有sql配置文件,以及关于数据库mybatis的配置信息(数据库:用户名,密码以及连接的url,mybatis配置信息中有是否开启懒加载,开启日志)。

       ②。 下一步,生成SqlSessionFactory对象,对象类型是SqlSessionFactory。

       ③。 又生成session对象,对象类型是sqlsession。(整个程序的执行也就到sqlsession,sqlsession是用来干活的)

        ④。通过session调用getMapper创建代理对象。(这里不做过多阐述)

1.3 sqlSession

sqlsession会执行sql语句

        Executor:执行器就是执行程序的,执行sql语句,所有的增删改查。

对象是堆里面的一块内存空间。

 


介绍local catch

        比如

                要对数据库进行查询:select * from A

        因为真正执行的是sqlsession,用sqlsession对他进行查询,查询到的数据会缓存到local catch本地缓存中,下一次再查询,就不用查询数据库了,直接从本地缓存中拿取。

<select id="FindStudentById" parameterType="int" resultType="com.qcby.entity.Student">select * from student where id=#{id}
</select>
Student FindStudentById(int id);

$1. 首次进行: 

@Testpublic void FindStudentById(){mapper.FindStudentById(1);}

结果:

$2. 执行两次:

    @Testpublic void FindStudentById(){mapper.FindStudentById(1);mapper.FindStudentById(1);}

结果:

执行两次查询,但是sql语句只执行一次。

为什么?

        因为第二次查询从本地缓存查数据。

 

@Test
public void FindStudentById1() {Student student1=mapper.FindStudentById(1);Student student2=mapper.FindStudentById(1);System.out.println(student2==student1);
}

   注!!

             值是true, 表明指向的是同一个地址空间,指向的是同一个对象。

这里只执行一次的sql语句与一级缓存有关,也叫sqlSession级别的缓存。


2. 缓存

2.1 概念

  • 存储在内存当中的数据
  • 将用户常使用的数据存放在缓存(内存)当中,用户查询数据就不用从磁盘(关系型数据库文件)当中查询,从缓存当中查询,从而提高查询效率,解决了高并发系统的性能问题

 2.2 使用缓存的原因

        减少和数据库的交互次数,减少系统开销,提高系统效率。

2.3 什么样的数据能使用缓存

        经常查询并且不常改变的数据。


3.  Mybatis缓存

        mybatis包含了一个非常强大的查询缓存特性,他可以非常方便的定制和配置缓存。缓存可以极大的提高查询的效率

        mybatis系统当中默认定义了两级缓存:一级缓存二级缓存

  • 默认情况之下,只有一级缓存开启(sqlSession级别的缓存)
  • 二级缓存需要手动开启配置,需要局域namespace级别的缓存。

 3.1 一级缓存

一级缓存也叫本地缓存

        与数据库同一次会话期间查询到的数据会放入的本地缓存当中。

        如果以后需要获取相同的数据直接去缓存当中拿,没必要再去查询数据库。


3.1.1 测试一级缓存

public class UserTest {private InputStream in = null;private SqlSession session = null;private UserDao mapper = null;/*** 测试查询所有的方法*/@Testpublic void findById() throws IOException {//加载主配置文件,目的是为了构建SqlSessionFactory对象in = Resources.getResourceAsStream("SqlMapConfig.xml");//创建SqlSessionFactory对象SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);//通过SqlSessionFactory工厂对象创建SqlSesssion对象session = factory.openSession();//通过Session创建UserDao接口代理对象mapper = session.getMapper(UserDao.class);User user1 = mapper.findById(1);System.out.println(user1.toString());System.out.println("-----------------");User user2 = mapper.findById(1);System.out.println(user2.toString());System.out.println(user1 == user2);//释放资源session.close();in.close();}
}


3.1.2  缓存失效的四种情况

  • sqlSession不同
  • sqlSession相同,查询条件不同
  • sqlSession相同,两次查询之间执行了增删改操作!
  • sqlSession相同,手动清除一级缓存
$1 sqlSession不同

$2  sqlSession相同,查询条件不同

        多次查询不同的情况,不会导致缓存失效。

$3  sqlSession相同,两次查询之间执行了增删改操作

$4 sqlSession相同,手动清除一级缓存


3.2 二级缓存

        二级缓存默认情况下是关闭的。

        想要开启的话,涉及到四个条件。

        二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactroy创建SqlSession查询结果会被缓存;此后若再次执行相同的查询语句,结果会从一个缓存中获取。

3.2.1 二级缓存开启的条件

①:在核心配置文件中,设置全局属性caheEnable="true"。

②:在映射件中置

③:查询数据所转换的实体类类型必须实现序列化接口

④:二级缓存必须在SqlSession关闭或提交之后有效

3.2.2 二级缓存失效的情况

        两次查询之间行了任意的增删改,会使得一级二级缓存同时失效。

3.2.3 开启二级缓存

$1 . 在SqlMapConfig.xml配置文件中开启二级缓存

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

$2..  在UserDao.xml配置文件声明使用二级缓存

<!--使用二级缓存-->
<cache/>

$3:  查询数据所转换的实体类类型必须实现序列化接口

public class User implements Serializable {private Integer id;private String username;private Date birthday;private String sex;private String address;// get set方法 .....}

$4 : 二级缓存必须在SqlSession关闭或提交之后有效

@Test
public void findById() throws IOException {// 1.加载SqlMapConfig配置文件InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");//2.创建sqlSessionFactory工厂SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);//3.sqlSessionFactory创建sqlSessionSqlSession sqlSession = factory.openSession();SqlSession sqlSession2 = factory.openSession();//4.通过Session创建UserDao接口代理对象UserDao mapper = sqlSession.getMapper(UserDao.class);User user1 = mapper.findById(1);System.out.println(user1.toString());// 将其一级缓存的数据放进二级缓存中,并清空一级缓存sqlSession.close();System.out.println("-----------------");UserDao mapper2 = sqlSession2.getMapper(UserDao.class);User user2 = mapper2.findById(1);System.out.println(user2.toString());// 将其一级缓存的数据放进二级缓存中,并清空一级缓存sqlSession2.close();System.out.println(user1 == user2);resourceAsStream.close();
}

结果:


3.2.4 分析 

$1. 

@Test
public void FindStudentById1() {Student student1=mapper1.FindStudentById(1);session1.close();//一级缓存失效或提交Student student2=mapper1.FindStudentById(1);//这里用的是sqlsession2System.out.println(student2==student1);
}

        这样写不对,因为此时session1已经关闭,如果下面继续用session1会报错。

$2. 

@Test
public void FindStudentById1() {Student student1=mapper1.FindStudentById(1);session1.close();Student student2=mapper2.FindStudentById(1);//这里用的是sqlsession2System.out.println(student2==student1);
}

        用session2去查询能够命中数据,因为session1查询到的数据提交到了sqlsessionFactory对象中,对象是堆里的 一段内存空间,里有catch,关闭sqlsession1之后,数据会放到sqlSessionFactory当中的catch,当执行sqlsession2时,从catch中取,0.5说明缓存命中率是一半(即存入的sqlSession1结果)。


 3.2.5 重要结论

        打印发现2个对象的地址值不一样,但是确实只发送了一次SQL语句的查询,二级缓存中存储的是数据,不是对象

        一级缓存缓存的是对象,就是查询出的对象,所以前用student1和student2是true,是同一个对象。

 3.3 Catch参数的具体细节

1. eviction(收回策略)--catch满了,回收数据

  • LRU(最近最少使用的):移除最长时间不被使用的对象,这是默认值。
  • FIFO(先进先出):按对象进入缓存的顺序来移除它们。
  • SOFT(软引用):移除基于垃圾回收器状态和软引用规则的对象。
  • WEAK(弱引用):更积极地移除基于垃圾收集器状态和弱引用规则的对象。

2. flushinterval(刷新间隔) 可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。

  • 默认情况不设置,即没有刷新间隔,缓存仅仅在调用语句时刷新。

原因

        数据库里的数据和缓存里的数据保持一致,故要间隔一段时间取访问数据库。

3. size(引用数目)--缓存的大小

  • 可以被设置为任意正整数,要记住缓存的对象数目和运行环境的可用内存资源数目。默认值是1024 。

4. readOnly(只读) 属性可以被设置为 true / false。

    • true:只读缓存:会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改, 这提供了很重要的性能优势。
    • false读写缓存: 通过序列化返回缓存对象的拷贝,这种方式会慢一些,但是安全,因此默认是 false。

配置结果

<cache eviction="FIFO"
flushInterval="6000"
size="512"
readOnly="true"/>

4. Mybatis缓存查询顺序

先查询二级缓存,因为二级缓存中可能会有其他程序查询出来的数据,可以直接拿来使用

如果二级缓存未命中,再查询一级缓存

如果一级缓存也没有命中,则查询数据库

SqlSession关闭之后,一级缓存的数据会写入二级缓存

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

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

相关文章

前端成长之路:CSS元素显示模式

元素显示模式 网页中的标签非常的多&#xff0c;在不同的地方会使用到不同类型的标签&#xff0c;了解这些标签的特点可以更好的布局我们的网页。 元素显示模式就是元素&#xff08;标签&#xff09;按照什么方式进行显示&#xff0c;比如&#xff1a;div标签会自己独占一行&a…

Unity类银河战士恶魔城学习总结(P178 Archer s arrow 弓箭手的箭)

【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili 教程源地址&#xff1a;https://www.udemy.com/course/2d-rpg-alexdev/ 本章节制作了一个弓箭手的箭 Arrow_Controller.cs 1.OnTriggerEnter2D方法 功能&#xff1a;检测箭矢与其他对象的碰撞。逻辑&#xff1…

机器学习周报(12.9-12.15)

文章目录 摘要Abstract 1 Swin Transformer1.1 输入1.2 Patch Partition1.3 Linear Embedding1.4 Patch Merging1.5 Swin Transformer Block1.6 代码总结 摘要 本篇博客介绍了采用类似于卷积核的移动窗口进行图像特征提取的Swin Transformer网络模型&#xff0c;这是一种基于T…

【C++游记】Vector的使用和模拟实现

枫の个人主页 你不能改变过去&#xff0c;但你可以改变未来 算法/C/数据结构/C Hello&#xff0c;这里是小枫。C语言与数据结构和算法初阶两个板块都更新完毕&#xff0c;我们继续来学习C的内容呀。C是接近底层有比较经典的语言&#xff0c;因此学习起来注定枯燥无味&#xf…

Jenkins流水线初体验(六)

DevOps之安装和配置 Jenkins (一) DevOps 之 CI/CD入门操作 (二) Sonar Qube介绍和安装(三) Harbor镜像仓库介绍&安装 (四) Jenkins容器使用宿主机Docker(五) Jenkins流水线初体验(六) 一、Jenkins流水线任务介绍 之前采用Jenkins的自由风格构建的项目,每个步骤…

Android后端签到flask迁移到rust的axum的过程-签到性能和便携

本次变更了以下内容: 为了使用之前ip2sta的ip到端点名的python,dic变量,将其存入redis hashset.使用地址/api/ip2dic 手动执行之.并且定义在/station/init,这个每天初始化redis的路径下.在rust axum使用redis 连接池在test中 ip2dic,IP转端点名,转本日此端网址.在前端的人名下…

Python OCR文字识别api接口

一.引言 文字识别&#xff0c;也称为光学字符识别&#xff08;Optical Character Recognition, OCR&#xff09;&#xff0c;是一种将不同形式的文档&#xff08;如扫描的纸质文档、PDF文件或数字相机拍摄的图片&#xff09;中的文字转换成可编辑和可搜索的数据的技术。随着技…

.NET 6.0 中接入 Log4net 和 NLog

一、接入Log4net 1.按日期和大小混合分割日志 nuget包安装 log4net Microsoft.Extensions.Logging.Log4Net.AspNetCore 配置文件 配置文件内容为 <?xml version"1.0" encoding"utf-8"?> <log4net> <!-- Define some output appe…

编写php项目所需环境

需要编写php项目&#xff0c;需要看到编写的代码展现的效果&#xff0c;这里我选择用xampp来展现 准备工作&#xff1a; https://learncodingfast.com/how-to-install-xampp-and-brackets/#Installing_and_Running_XAMPP xampp下载地址&#xff1a;https://www.apachefriends.…

树莓派Pico火灾报警器项目:基于火焰传感器、蜂鸣器与LED的C++实现

火灾是我们生活中一个不可忽视的安全隐患,而火灾报警系统在预防火灾和保障人员安全方面起着至关重要的作用。通过嵌入式技术,我们可以实现一个简单而有效的火灾报警装置。在本项目中,我们将利用 树莓派Pico 控制 火焰传感器、LED 和 蜂鸣器,模拟火灾报警装置的工作原理。本…

数学建模问题中的多目标规划

多目标规划&#xff08;Multi-Objective Optimization, MOO&#xff09;是指在优化问题中同时优化多个相互冲突的目标函数的情况。与单目标优化问题不同&#xff0c;多目标优化的解通常不再是唯一的&#xff0c;而是一个解的集合&#xff0c;称为帕累托最优解集。这些解在所有目…

智汇云舟4个案例入选“中国联通智慧城市物联感知与AI应用案例”

12月10日&#xff0c;由中国联通智慧城市军团联合联通数字科技有限公司物联网事业部、物联中国团体组织联席会共同主办的“中国联通首届智慧城市领域物联感知与AI应用优秀案例发布交流大会”在郑州举行。大会现场对50余个优秀案例进行了集中发布与表彰。智汇云舟凭借深厚的技术…

【JavaEE】网络(1)

&#x1f435;本篇文章开始讲解计算机网络相关的知识 一、基础概念 1.1 局域网和广域网 局域网→Local Area Network→简称LAN&#xff0c;局域网是局部组建的一种私有网络&#xff0c;局域网内的主机之间可以进行网络通信&#xff0c;局域网和局域网之间在没有连接的情况不能…

Unity 模板测试透视效果(URP)

可以实现笼中窥梦和PicoVR中通过VST局部透视效果。 使用到的Shader: Shader "Unlit/StencilShader" {Properties{[IntRange]_Index("Stencil Index",Range(0,255))0}SubShader{Tags{"RenderType""Opaque""Queue""Geo…

川渝地区软件工程考研择校分析

通过最新数据分析,5所高校软件工程专业2025年考研难度从高到低预计为: 电子科技大学 >> 四川大学 > 重庆大学 ≈ 西南交通大学 > 西南大学 对于想考川渝地区985但核心目标为优先上岸的考生,建议重点考虑西南交通大学软件工程学硕。该校24届软件工程学硕实际录取1…

KeepAlive与RouterView缓存

参考 vue动态组件&#xff1c;Component&#xff1e;与&#xff1c;KeepAlive&#xff1e; KeepAlive官网介绍 缓存之keep-alive的理解和应用 Vue3Vite KeepAlive页面缓存问题 vue多级菜单(路由)导致缓存(keep-alive)失效 vue3 router-view keeperalive对于同一路径但路径…

《拉依达的嵌入式\驱动面试宝典》—C/CPP基础篇(五)

《拉依达的嵌入式\驱动面试宝典》—C/CPP基础篇(五) 你好,我是拉依达。 感谢所有阅读关注我的同学支持,目前博客累计阅读 27w,关注1.5w人。其中博客《最全Linux驱动开发全流程详细解析(持续更新)-CSDN博客》已经是 Linux驱动 相关内容搜索的推荐首位,感谢大家支持。 《拉…

《拉依达的嵌入式\驱动面试宝典》—C/CPP基础篇(四)

《拉依达的嵌入式\驱动面试宝典》—C/CPP基础篇(四) 你好,我是拉依达。 感谢所有阅读关注我的同学支持,目前博客累计阅读 27w,关注1.5w人。其中博客《最全Linux驱动开发全流程详细解析(持续更新)-CSDN博客》已经是 Linux驱动 相关内容搜索的推荐首位,感谢大家支持。 《拉…

短波红外相机

短波红外相机搭载采用 SenSWIR 技术的 Sony 高灵敏度传感器&#xff0c;能捕获到400nm~1700nm范围的可见光-短波红外宽波段图像信息&#xff0c;该相机可替代传统的“可见光相机短波红外相机”双相机检测方案&#xff0c;降低系统成本、提高处理速度、扩大检测范围&#xff0c;…

系统安全——访问控制访问控制

访问控制 概念 什么是访问控制 access control 为用户对系统资源提供最大限度共享的基础上&#xff0c;对用户的访问权进行管理&#xff0c;防止对信息的非授权篡改和滥用 ​ 访问控制作用 保证用户在系统安全策略下正常工作 拒绝非法用户的非授权访问请求 拒绝合法用户越权…