浅谈Mybatis的一级缓存和二级缓存
MyBatis的缓存机制
缓存的引入
当我们大量执行重复的查询SQL语句的时候,会频繁的和数据库进行通信,会增加查询时间等影响用户体验的问题,可以通过缓存,以降低网络流量,使网站加载速度更快.
MyBatis的一级缓存
默认情况下,MyBatis只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。这也就是大家常说的MyBatis一级缓存,一级缓存的作用域是SqlSession。
第1种情况:同个session进行两次相同查询
代码验证
//测试一级缓存@Testpublic void testCache() throws IOException {//加载配置文件InputStream rs = Resources.getResourceAsStream("MyBatisConfig.xml");//获取工厂建造类SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();//获取工厂对象SqlSessionFactory build = sqlSessionFactoryBuilder.build(rs);//获取SqlSession对象SqlSession sqlSession = build.openSession(true);//得到代理的对象StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);//根据名字查询Student stu1 = mapper.findStudentByName("小花花");Student stu2 = mapper.findStudentByName("小花花");/*这里相等,说明默认开启一级缓存,就是在同一个sqlSession域中有效,只要查询相同的语句,就是从一级缓存中获取*/System.out.println("两次查询结果的学生对象是否是同一个:"+(stu1==stu2));//关闭会话sqlSession.close();rs.close();}
执行结果
由上面的执行结果得知
MyBatis是默认开启一级缓存的,作用域是同一个SqlSession,在同一个sqlSession中查询相同的sql语句,第一次查询后会将结果对象存放在一级缓存中,在后面查询相同的sql语句的时候会在一级缓存中去获取,不用在与数据库进行通信,大大降低了查询速度.
第2种情况:同个session进行两次不同的查询。
** 代码演示**
//测试一级缓存@Testpublic void testCache() throws IOException {//加载配置文件InputStream rs = Resources.getResourceAsStream("MyBatisConfig.xml");//获取工厂建造类SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();//获取工厂对象SqlSessionFactory build = sqlSessionFactoryBuilder.build(rs);//获取SqlSession对象SqlSession sqlSession = build.openSession(true);//得到代理的对象StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);//根据名字查询Student stu1 = mapper.findStudentByName("小花花");Student stu2 = mapper.findStudentByName("小付");System.out.println("两次查询结果的学生对象是否是同一个:"+(stu1==stu2));//关闭会话sqlSession.close();rs.close();}
控制台输出
第3种情况:不同session,进行相同查询。
** 代码演示**
//测试一级缓存@Testpublic void testCache() throws IOException {//加载配置文件InputStream rs = Resources.getResourceAsStream("MyBatisConfig.xml");//获取工厂建造类SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();//获取工厂对象SqlSessionFactory build = sqlSessionFactoryBuilder.build(rs);//获取SqlSession对象SqlSession sqlSession = build.openSession(true);StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);//获取SqlSession2对象SqlSession sqlSession2 = build.openSession(true);StudentMapper mapper2 = sqlSession2.getMapper(StudentMapper.class);//根据名字查询Student stu1 = mapper.findStudentByName("小花花");Student stu2 = mapper2.findStudentByName("小花花");System.out.println("两次查询结果的学生对象是否是同一个:"+(stu1==stu2));//关闭会话sqlSession.close();rs.close();}
控制台输出
第4种情况:同个session,查询之后更新数据,再次查询相同的语句。
代码演示
//测试一级缓存@Testpublic void testCache() throws IOException {//加载配置文件InputStream rs = Resources.getResourceAsStream("MyBatisConfig.xml");//获取工厂建造类SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();//获取工厂对象SqlSessionFactory build = sqlSessionFactoryBuilder.build(rs);//获取SqlSession对象SqlSession sqlSession = build.openSession(true);//得到代理的对象StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);//根据名字查询Student stu1 = mapper.findStudentByName("小花花");//修改数据stu1.setAge(18);//执行更新语句mapper.updateStudent(stu1);//再次查询Student stu2 = mapper.findStudentByName("小花花");System.out.println("两次查询结果的学生对象是否是同一个:"+(stu1==stu2));//关闭会话sqlSession.close();rs.close();}
控制台输出
一级缓存结论
MyBatis一级缓存的运行过程是这样的:执行SQL语句的过程中,首次执行它时从数据库获取的所有数据会被存储在一段高速缓存中,今后执行这条语句时就会从高速缓存中读取结果,而不是再次查询数据库。MyBatis提供了默认下基于Java HashMap的缓存实现。
重点是要明白:MyBatis执行SQL语句之后,这条语句的执行结果被缓存,以后再执行这条语句的时候,会直接从缓存中拿结果,而不是再次执行SQL。但是一旦执行新增或更新或删除操作,缓存就会被清除。下面将分情况来验证一下。
很明显,以上各种情况验证了一级缓存的概念,在同个SqlSession中,查询语句相同的sql会被缓存,但是一旦执行新增或更新或删除操作,缓存就会被清除。
MyBatis的二级缓存(全局缓存)
引入
MyBatis 一级缓存最大的共享范围就是一个SqlSession内部,那么如果多个 SqlSession 需要共享缓存,则需要开启二级缓存.
当二级缓存开启后,同一个命名空间(namespace) 所有的操作语句,都影响着一个共同的 cache,也就是二级缓存被多个 SqlSession 共享,是一个全局的变量。当开启缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。
二级缓存开启条件
二级缓存默认是不开启的,需要手动开启二级缓存,实现二级缓存的时候,MyBatis要求返回的**POJO必须是可序列化的**。开启二级缓存的条件也是比较简单.
在MyBatis核心配置文件中配置开启二级缓存
<!-- 通知 MyBatis 框架开启二级缓存 -->
<settings><setting name="cacheEnabled" value="true"/>
</settings>
在mapper配置文件中开启当前命名空间的查询结果存放在二级缓存中
<!-- 表示DEPT表查询结果保存到二级缓存(共享缓存)cache 标签有多个属性,一起来看一些这些属性分别代表什么意义eviction: 缓存回收策略,有这几种回收策略LRU - 最近最少回收,移除最长时间不被使用的对象FIFO - 先进先出,按照缓存进入的顺序来移除它们SOFT - 软引用,移除基于垃圾回收器状态和软引用规则的对象WEAK - 弱引用,更积极的移除基于垃圾收集器和弱引用规则的对象默认是 LRU 最近最少回收策略flushinterval 缓存刷新间隔,缓存多长时间刷新一次,默认不清空,设置一个毫秒值readOnly: 是否只读;true 只读,MyBatis 认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。MyBatis 为了加快获取数据,直接就会将数据在缓存中的引用交给用户。不安全,速度快。读写(默认):MyBatis 觉得数据可能会被修改size : 缓存存放多少个元素type: 指定自定义缓存的全类名(实现Cache 接口即可)blocking: 若缓存中找不到对应的key,是否会一直blocking,直到有对应的数据进入缓存。我这里就使用默认的,不去设置参数--><cacheeviction="FIFO"flushInterval="60000"size="512"readOnly="true"/>
实体类对象要Serializable序列化
@Data //这个注解是lombok包下的,可以自动帮我们添加getset方法等
public class Student implements Serializable {private Integer sid;private String name;private Integer age;
}
代码验证
//测试一级缓存@Testpublic void testCache() throws IOException {//加载配置文件InputStream rs = Resources.getResourceAsStream("MyBatisConfig.xml");//获取工厂建造类SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();//获取工厂对象SqlSessionFactory build = sqlSessionFactoryBuilder.build(rs);//获取SqlSession对象SqlSession sqlSession = build.openSession(true);StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);//根据名字查询Student stu1 = mapper.findStudentByName("小花花");System.out.println("第一次查出的对象"+stu1);//关闭会话后,会将一级缓存的数据保存在二级缓存中sqlSession.close();//获取SqlSession2对象SqlSession sqlSession2 = build.openSession(true);StudentMapper mapper2 = sqlSession2.getMapper(StudentMapper.class);//新的会话查询就会从二级缓存中获取数据Student stu2 = mapper2.findStudentByName("小花花");System.out.println("第二次查出的对象"+stu1);System.out.println("两次查询结果的学生对象是否是同一个:"+(stu1==stu2));//关闭会话sqlSession2.close();rs.close();}
控制台输出
图解查询语句执行流程
浅谈Mybatis的一级缓存和二级缓存相关推荐
- 浅谈MyBatis二级缓存
一.二级缓存介绍 我们知道MyBatis 提供了一级缓存来减轻数据库的压力,但是一级缓存是一个SqlSession(会话)级别的缓存,这也就意味着一级缓存的适用范围比较小.在一级缓存的基础上,MyBa ...
- Mybatis一级缓存,二级缓存的实现就是这么简单
介绍 又到了一年面试季,所以打算写一点面试常问的东西,争取说的通俗易懂.面试高级岗,如果你说熟悉Mybatis,下面这些问题基本上都会问 Mybatis插件的实现原理? 如何写一个分页插件? Myba ...
- mybatis高级(3)_延迟加载_深度延迟_一级缓存_二级缓存
设置延迟加载需要在mybatis.xml中设置 注: 侵入式延迟加载为真时是延迟加载 侵入式延迟加载为假时是深度延迟加载 <!-- 延迟加载和深度延迟加载 --><settings& ...
- MyBatis框架:延迟加载策策略、一级缓存、二级缓存
MyBatis框架:延迟加载策略和缓存 Mybatis 延迟加载策略 1.1 何为延迟加载? 1.2 实现需求 1.3 使用association实现延迟加载 1.3.1 账户的持久层DAO接口 1. ...
- MyBatis】MyBatis一级缓存和二级缓存
转载自 MyBatis]MyBatis一级缓存和二级缓存 MyBatis自带的缓存有一级缓存和二级缓存 一级缓存 Mybatis的一级缓存是指Session缓存.一级缓存的作用域默认是一个SqlSe ...
- Mybatis 详解--- 一级缓存、二级缓存
2019独角兽企业重金招聘Python工程师标准>>> Mybatis 为我们提供了一级缓存和二级缓存,可以通过下图来理解: ①.一级缓存是SqlSession级别的缓存.在操作数据 ...
- Mybatis源码分析之(七)Mybatis一级缓存和二级缓存的实现
文章目录 一级缓存 二级缓存 总结 对于一名程序员,缓存真的很重要,而且缓存真的是老生常谈的一个话题拉.因为它在我们的开发过程中真的是无处不在.今天LZ带大家来看一下.Mybatis是怎么实现一级缓存 ...
- 框架源码专题:Mybatis的一级缓存、二级缓存是什么?有什么作用?
文章目录 1. Mybatis中缓存的作用 2. 一级缓存 3. 二级缓存 4. 一级缓存和二级缓存的区别 5. 通过代码观察Mybatis缓存工作的全过程 1. Mybatis中缓存的作用 首先缓存 ...
- MyBatis中的一级缓存和二级缓存介绍
先说缓存,合理使用缓存是优化中最常见的,将从数据库中查询出来的数据放入缓存中,下次使用时不必从数据库查询,而是直接从缓存中读取,避免频繁操作数据库,减轻数据库的压力,同时提高系统性能. 一级缓存 一级 ...
最新文章
- POJ1001--Exponentiation(幂计算)翻译
- 前端编程提高之旅(五)----写给大家看的css书
- 计算机教资笔试答题,教资笔试5大题型的解答技巧,你get到了嘛?
- Java SE、Java EE、Java ME基本区别
- EOS 源代码解读 (4)交易数据结构
- 异想-天开 python---while、for、if-else 循环学习
- 【Protocol Buffer】Protocol Buffer入门教程(四):序列化和反序列化
- ssm框架重定向_Java SSM 框架面试题,附答案!
- Dungeon Master(三维bfs)
- SAP MM模块-实施顾问岗位-面试手册-面试总结
- 虚拟机网络无法连接问题解决(超简单)
- 如何让强化学习走进现实世界?DeepMind要用“控制套件”推动
- pyinstaller 打包后报错 ModuleNotFoundError: No module named ‘***‘ 最简单解决方案
- 根目录下的/lib64也不能删除
- 【邱锡鹏老师SMP2020教程】90页自然语言处理中的预训练模型
- sql数据库置疑解决办法
- Android开发中自定义表情并发送出去之经典的发送表情
- java基础继承合集
- App Designer中自建回调函数
- 人工神经网络有哪些应用,人工神经网络包括哪些