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的一级缓存和二级缓存相关推荐

  1. 浅谈MyBatis二级缓存

    一.二级缓存介绍 我们知道MyBatis 提供了一级缓存来减轻数据库的压力,但是一级缓存是一个SqlSession(会话)级别的缓存,这也就意味着一级缓存的适用范围比较小.在一级缓存的基础上,MyBa ...

  2. Mybatis一级缓存,二级缓存的实现就是这么简单

    介绍 又到了一年面试季,所以打算写一点面试常问的东西,争取说的通俗易懂.面试高级岗,如果你说熟悉Mybatis,下面这些问题基本上都会问 Mybatis插件的实现原理? 如何写一个分页插件? Myba ...

  3. mybatis高级(3)_延迟加载_深度延迟_一级缓存_二级缓存

    设置延迟加载需要在mybatis.xml中设置 注: 侵入式延迟加载为真时是延迟加载 侵入式延迟加载为假时是深度延迟加载 <!-- 延迟加载和深度延迟加载 --><settings& ...

  4. MyBatis框架:延迟加载策策略、一级缓存、二级缓存

    MyBatis框架:延迟加载策略和缓存 Mybatis 延迟加载策略 1.1 何为延迟加载? 1.2 实现需求 1.3 使用association实现延迟加载 1.3.1 账户的持久层DAO接口 1. ...

  5. MyBatis】MyBatis一级缓存和二级缓存

    转载自  MyBatis]MyBatis一级缓存和二级缓存 MyBatis自带的缓存有一级缓存和二级缓存 一级缓存 Mybatis的一级缓存是指Session缓存.一级缓存的作用域默认是一个SqlSe ...

  6. Mybatis 详解--- 一级缓存、二级缓存

    2019独角兽企业重金招聘Python工程师标准>>> Mybatis 为我们提供了一级缓存和二级缓存,可以通过下图来理解: ①.一级缓存是SqlSession级别的缓存.在操作数据 ...

  7. Mybatis源码分析之(七)Mybatis一级缓存和二级缓存的实现

    文章目录 一级缓存 二级缓存 总结 对于一名程序员,缓存真的很重要,而且缓存真的是老生常谈的一个话题拉.因为它在我们的开发过程中真的是无处不在.今天LZ带大家来看一下.Mybatis是怎么实现一级缓存 ...

  8. 框架源码专题:Mybatis的一级缓存、二级缓存是什么?有什么作用?

    文章目录 1. Mybatis中缓存的作用 2. 一级缓存 3. 二级缓存 4. 一级缓存和二级缓存的区别 5. 通过代码观察Mybatis缓存工作的全过程 1. Mybatis中缓存的作用 首先缓存 ...

  9. MyBatis中的一级缓存和二级缓存介绍

    先说缓存,合理使用缓存是优化中最常见的,将从数据库中查询出来的数据放入缓存中,下次使用时不必从数据库查询,而是直接从缓存中读取,避免频繁操作数据库,减轻数据库的压力,同时提高系统性能. 一级缓存 一级 ...

最新文章

  1. POJ1001--Exponentiation(幂计算)翻译
  2. 前端编程提高之旅(五)----写给大家看的css书
  3. 计算机教资笔试答题,教资笔试5大题型的解答技巧,你get到了嘛?
  4. Java SE、Java EE、Java ME基本区别
  5. EOS 源代码解读 (4)交易数据结构
  6. 异想-天开 python---while、for、if-else 循环学习
  7. 【Protocol Buffer】Protocol Buffer入门教程(四):序列化和反序列化
  8. ssm框架重定向_Java SSM 框架面试题,附答案!
  9. Dungeon Master(三维bfs)
  10. SAP MM模块-实施顾问岗位-面试手册-面试总结
  11. 虚拟机网络无法连接问题解决(超简单)
  12. 如何让强化学习走进现实世界?DeepMind要用“控制套件”推动
  13. pyinstaller 打包后报错 ModuleNotFoundError: No module named ‘***‘ 最简单解决方案
  14. 根目录下的/lib64也不能删除
  15. 【邱锡鹏老师SMP2020教程】90页自然语言处理中的预训练模型
  16. sql数据库置疑解决办法
  17. Android开发中自定义表情并发送出去之经典的发送表情
  18. java基础继承合集
  19. App Designer中自建回调函数
  20. 人工神经网络有哪些应用,人工神经网络包括哪些

热门文章

  1. 一步步学习SPD2010--第七章节--使用BCS业务连接服务
  2. Ajax设置自定义请求头的两种方法
  3. WannaCry勒索软件还在继续传播和感染中
  4. 非常不错的MySQL优化的8条经验
  5. 经Apache将tomcat转用80port这两个域名
  6. 实践理解计算机启动过程
  7. idea常用但容易忘记的快捷键
  8. Factom(公证通)--基于区块链的存证系统
  9. Wordpress安装简要说明
  10. 《嵌入式Linux软硬件开发详解——基于S5PV210处理器》——2.2 DDR2 SDRAM芯片