【MyBatis】第八篇:一级,二级缓存

news2024/11/29 2:49:23

其实缓存字面的意思就是将一些内容缓存下来,等下次使用的时候可以直接调用,通过数据库得到数据,有时候会使用相同的数据,所以mybatis自然也支持缓存。

而mybatis按照缓存的效果可以分两大类:一级缓存和二级缓存。

一级缓存

其实一级缓存是SqlSession级别,通过SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库中重写访问。

还是老规矩进行代码演示:

List<Student>  getStudent();
   <select id="getStudent" resultType="Student">
        SELECT sid , sname , sage , ssex , gid FROM testmybatis.student
   </select>

然后调用的时候,不关闭SqlSession,然后连续调用getStudent() :

   System.out.println("  --------------------  第一次     " + studentMapper.getStudent());
   System.out.println("  --------------------  第二次     " + studentMapper.getStudent());

在这里插入图片描述

可以看出sql语句,只是调用了一次,但是还是得到了数据。

但是一级缓存也是会失效的,其中有四种情况:

  • 不同的SqlSession对应不同一级缓存,比如例子一直说用的同一个sqlsession,也没有关闭sqlsession重写创建了一个。

  • 同一个SqlSession,但是两次查询的条件不同,甚至是操作相同,但是方法名不同,也不会调用缓存,可以看下演示:

        List<Student>  getStudent();
        List<Student>  getStudent1();
    
       <select id="getStudent" resultType="Student">
    
            SELECT sid , sname , sage , ssex , gid FROM testmybatis.student
        </select>
        <select id="getStudent1" resultType="Student">
    
            SELECT sid , sname , sage , ssex , gid FROM testmybatis.student
        </select>
    

    然后调用:

            System.out.println("  --------------------  第一次     " + studentMapper.getStudent());
            System.out.println("  --------------------  第二次     " + studentMapper.getStudent());
    
            System.out.println("  --------------------  另一个第一次     " + studentMapper.getStudent1());
    
            System.out.println("  --------------------  第三次     " + studentMapper.getStudent());
    

在这里插入图片描述

可以看出哪怕同一个sqlsession其一样的sql语句,通过两个不同方法也不会调用缓存,因为sql语句执行了两次。当然其也不会影响已缓存是数据。

  • 同一个sqlsession同一个查询,在两者依次执行期间,执行了任何依次增改操作。

    来实体体验一把:

        List<Student>  getStudent();
    
        void  deleteStudent();
    
     <select id="getStudent" resultType="Student">
    
            SELECT sid , sname , sage , ssex , gid FROM testmybatis.student
        </select>
    
        <delete id="deleteStudent">
              <!--这里删除一个不存在的数据 -->
            delete from   testmybatis.student where  sid='100'
        </delete>
    
            System.out.println("  --------------------  第一次     " + studentMapper.getStudent());
            studentMapper.deleteStudent();
            System.out.println("  --------------------  第二次     " + studentMapper.getStudent());
    

在这里插入图片描述

可以看出其删除无论是否存在

  • 同一个SqlSession两次执行同一个查询中介,执行了手动清楚缓存。

      System.out.println("  --------------------  第一次     " + studentMapper.getStudent());
    //  调用clearCache() 手动清楚了缓存
      sqlSession.clearCache();
      System.out.println("  --------------------  第二次     " + studentMapper.getStudent());
    

在这里插入图片描述

二级缓存

二级缓存是SqlSessionFactory级别的,同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存,此后执行相同的查询语句,数据就会从缓存中得到。

启用的条件:

  • 在核心配置文件中,加入配置:<setting name="cacheEnabled"value="true" />
  • 在映射文件中加入<cache />
  • 查询的数据转换的实体类类型,必须实现序列化接口Serializable
  • SqlSession在关闭或者提交以后二级缓存才会有效。

还是老规矩进行演示:

前提在核心配置文件mybatis-config.xml中配置

   <settings>
        <setting name="cacheEnabled" value="true" />
    </settings>

然后再映射文件中添加:

 <cache></cache>

实体类需要实现序列化接口:

public class Student  implements Serializable

现在开始演示:

        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//        这个通过代理模式,传入什么类返回什么类
        StudentMapper  studentMapper = sqlSession.getMapper(StudentMapper.class);
        System.err.println("  --------------------  第一次         sqlSession  -- getStudent     " + studentMapper.getStudent());
       // 不关闭的话,
        sqlSession.close();
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        StudentMapper  studentMapper1 = sqlSession1.getMapper(StudentMapper.class);

        System.err.println("  --------------------  第一次    sqlSession1 --  方法名为 getStudent  " + studentMapper1.getStudent());
        System.err.println("  --------------------  第一次     sqlSession1 -- 方法名为 getStudent1   " + studentMapper1.getStudent1());
        studentMapper1.deleteStudent();
        System.err.println("  --------------------  第二次    sqlSession1 -- 执行deleteStudent后调用 getStudent  " + studentMapper1.getStudent());

        sqlSession1.close();

在这里插入图片描述

可以看出了只要删除或者修改了数据库,无论是一级缓存还是二级缓存都会同时失效。

这个又有一个疑问了,那就是一级缓存和二级缓存的查询顺序是什么?

先查询二级缓存,没有再查询二级缓存,如果还没有再查询数据库。

为什么会这样,因为二级缓存覆盖的更广,一级缓存中没有但是在二级缓存中,减少去数据库中取数的频次。

补充--------二级缓存的配置

其实再映射文件中可以配置一些属性:

看一下官网举出的例子:

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

eviction 属性是缓存回收策略,默认是LRU。

这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。

可用的清除策略有:

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

默认的清除策略是 LRU。

flushInterval(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。

size(引用数目)属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。

readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。

当然还有一个属性没有写,那就是type:其在使用第三方的缓存的时候使用,因为有些第三方的缓存的功能会更强大,所以有时候会使用第三方缓存,这个就下一篇具体聊。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

node.js下载和vite项目创建以及可能遇到的错误

目录 一、node.js的下载 1、去官网下载 节点.js (nodejs.org) 2、下载过程 第一步&#xff1a; 第二步&#xff1a; 第三步&#xff1a; 第四步&#xff1a; 第五步: 二、vite项目的创建&#xff08;使用的工具是Hbuilder x&#xff09; 第一步&#xff1a; 出现报错…

基于matlab多功能相控阵雷达资源管理的服务质量优化

一、前言此示例说明如何为基于服务质量 &#xff08;QoS&#xff09; 优化的多功能相控阵雷达 &#xff08;MPAR&#xff09; 监控设置资源管理方案。它首先定义必须同时调查的多个搜索扇区的参数。然后&#xff0c;它介绍了累积检测范围作为搜索质量的度量&#xff0c;并展示了…

低代码开发平台|制造管理-工艺工序搭建指南

1、简介1.1、案例简介本文将介绍&#xff0c;如何搭建制造管理-工艺工序。1.2、应用场景先填充工序信息&#xff0c;再设置工艺路线对应的工序&#xff1b;工序信息及工艺路线列表报表展示的是所有工序、工艺路线信息&#xff0c;可进行新增对应数据的操作。2、设置方法2.1、表…

权限管理实现的两种方式(详解)

登录的接口请求的三个内容&#xff1a;1. token2. 用户信息、角色信息3. 菜单信息第一种&#xff1a;基于角色Role的动态路由管理 (不推荐&#xff0c;但市场用的比较多)首先列出枚举每个角色对应几个路由&#xff0c;然后根据用户登录的角色遍历枚举出来的角色动态注册对应的路…

4年功能测试经验,裸辞后找不到工作怎么办?

软件测试四年&#xff0c;主要是手动测试&#xff08;部分自动化测试和性能测试&#xff0c;但是用的是公司内部自动化工具&#xff0c;而且我自动化方面是弱项。&#xff09; 现在裸辞三个月了&#xff0c;面试机会少而且面试屡屡受挫。总结就是自动化&#xff0c;性能&#…

微服务保护:一、初识Sentinel

1.1.雪崩问题及解决方案 1.1.1.雪崩问题 微服务中&#xff0c;服务间调用关系错综复杂&#xff0c;一个微服务往往依赖于多个其它微服务。 如图&#xff0c;如果服务提供者I发生了故障&#xff0c;当前的应用的部分业务因为依赖于服务I&#xff0c;因此也会被阻塞。此时&…

链接脚本学习笔记

IAR 一般步骤 链接器用于链接过程。它通常执行以下过程&#xff08;请注意&#xff0c;某些步骤可以通过命令行选项或链接器配置文件中的指令关闭&#xff09;&#xff1a; 1.确定应用程序中要包含哪些模块。始终包含对象文件中提供的模块。仅当库文件中的模块为从包含的模块…

智慧楼宇系统:商办楼宇运营方的不二之选

现在&#xff0c;许多商办楼宇运营方都倾向于选择专业的商办楼宇管理系统来完成日常运营管理&#xff0c;从而实现楼宇的高效运作。 那么问题来了&#xff0c;商办楼宇运营者该如何选购一个合适的楼宇管理系统&#xff1f;在选择系统之前&#xff0c;必须要清楚系统能解决哪些…

NODE => CORS跨域资源共享学习

1.CORS跨域资源共享 cors是Express的一个第三方中间件。通过安装和配置cors中间件&#xff0c;可以很方便地解决跨域问题 运行npm install cors 安装中间件使用const cors require(‘cors’) 导入中间件在路由之前调用 app.use&#xff08;cors&#xff08;&#xff09;&#…

Java · 常量介绍 · 变量类型转换 · 理解数值提升 · int 和 Stirng 之间的相互转换

书接上回 Java 变量介绍 我们继续学习以下内容. 四、常量字面值常量final 关键字修饰的常量五、理解类型转换int 和 long/double 相互赋值int 和 boolean 相互赋值int 字面值常量给 byte 赋值强制类型转换类型转换小结六、理解数值提升int 和 long 混合运算byte 和 byte 的运算…

大数据未来会如何发展

大数据应用的重要性&#xff0c;自全国提出“数据中国”的概念以来&#xff0c;我们周围默默地在发挥作用的大数据逐渐深入人们的心中&#xff0c;大数据的应用也越来越广泛&#xff0c;具体到金融、汽车、餐饮、电信、能源、体育和娱乐等领域 为什么大数据技术那么火&#xf…

机器学习之决策树原理详解、公式推导(手推)、面试问题、简单实例(python实现,sklearn调包)

目录1. 决策树原理1.1. 特性1.2. 思路1.3. 概念决策树概念信息论2. 公式推导2.1. 构造决策树2.1.1. ID3理论示例缺点2.1.2. C4.5理论示例缺点2.1.3. CART示例对比分析2.2. 剪枝3. 实例3.1. 数据集3.2. ID33.3. C4.53.4. CART3.5. sklearn实现4. 几个注意点(面试问题)5. 运行&am…

高性能MySQL -- 查询性能优化

一般来说一个好的程序&#xff1a;查询优化&#xff0c;索引优化&#xff0c;库表结构要同时进行优化。今天我们来讲一下查询优化。 我们需要对MySQL的架构有基本认知&#xff0c;所以这里贴一张图大家看看&#xff1a; 图片来自于《小林coding》 为什么从查询会慢&#xff1…

点云深度学习系列博客(四): 注意力机制原理概述

目录 1. 注意力机制由来 2. Nadaraya-Watson核回归 3. 多头注意力与自注意力 4. Transformer模型 Reference 随着Transformer模型在NLP&#xff0c;CV甚至CG领域的流行&#xff0c;注意力机制&#xff08;Attention Mechanism&#xff09;被越来越多的学者所注意&#xff0c;将…

九、Linux文件 - fopen函数和fclose函数讲解

目录 1.fopen函数 2.fclose函数 3.fopen函数和fclose实战 1.fopen函数 fopen fwrite fread fclose ...属于标准C库 include <stdio.h> standard io lib open close write read 属于Linux系统调用 可移植型&#xff1a;fopen > open&#xff08;open函数只在嵌入…

ES6的代理Proxy和反射Reflect的使用

一、Proxy使用 作用&#xff1a;Proxy是ES6为了操作对象而引入的API&#xff0c;不直接作用于对象&#xff0c;而是通过类似媒介的方式进行对象的操作使用 /*** target&#xff1a;需要proxy处理的对象* handler&#xff1a;对对象进行处理的方法 */ let proxy new Proxy(ta…

ARM uboot源码分析2-启动第一阶段

一、start.S 解析5 注释的中文含义&#xff1a; 当我们已经在 RAM 中运行时&#xff0c;我们不需要重新定位 U-Boot。实际上&#xff0c;在 U-Boot 在 RAM 中运行之前&#xff0c;必须配置内存控制器。 1、判断当前代码执行位置 (1) lowlevel_init.S 的 110-115 行。 (2) 这几…

5年经验之谈:月薪3000到30000,测试工程师的变“行”记!

自我介绍下&#xff0c;我是一名转IT测试人&#xff0c;我的专业是化学&#xff0c;去化工厂实习才发现这专业的坑人之处&#xff0c;化学试剂害人不浅&#xff0c;有毒&#xff0c;易燃易爆&#xff0c;实验室经常用丙酮&#xff0c;甲醇&#xff0c;四氯化碳&#xff0c;接触…

ESP32 Arduino(十二)lvgl移植使用

一、简介LVGL全程LittleVGL&#xff0c;是一个轻量化的&#xff0c;开源的&#xff0c;用于嵌入式GUI设计的图形库。并且配合LVGL模拟器&#xff0c;可以在电脑对界面进行编辑显示&#xff0c;测试通过后再移植进嵌入式设备中&#xff0c;实现高效的项目开发。SquareLine Studi…

RMI攻击中的ServerClient相互攻击反制

前言 前文中&#xff0c;我们分析了攻击Registry的两种方式&#xff0c;这里我们接着前面的内容&#xff0c;分析Server和Client的相互攻击方式。 Attacked Server Attacked By Client 首先我们搭建个示例&#xff0c;这里直接注册端和服务端放置在一起。 package pers.rm…