mybaits(8)-缓存机制

缓存机制

  • 1、mybatis缓存
  • 2、一级缓存
    • 2.1 开启一级缓存
    • 2.2 一级缓存失效
  • 3、二级缓存
    • 3.1 开启二级缓存
    • 3.2 二级缓存什么时候失效
    • 3.3 二级缓存的相关配置
  • 4、MyBatis集成EhCache

1、mybatis缓存

缓存:cache
缓存的作用:通过减少IO的方式,来提高程序的执行效率。
mybatis的缓存:将select语句的查询结果放到缓存(内存)当中,下一次还是这条select语句的话,直接从缓存中取,不再查数据库。一方面是减少了IO。另一方面不再执行繁琐的查找算法。效率大大提升。
mybatis缓存包括:
● 一级缓存:将查询到的数据存储到SqlSession中。
● 二级缓存:将查询到的数据存储到SqlSessionFactory中。
● 或者集成其它第三方的缓存:比如EhCache【Java语言开发的】、Memcache【C语言开发的】等。
缓存只针对于DQL语句,也就是说缓存机制只对应select语句。

2、一级缓存

2.1 开启一级缓存

一级缓存默认是开启的。不需要做任何配置。
原理:只要使用同一个SqlSession对象执行同一条SQL语句,就会走缓存。
测试:

  @Test
    public void test2() throws  Exception{
        SqlSession sqlSession = MybatisUtils.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = mapper.selectByid(8);
        System.out.println(car);
        Car car1 = mapper.selectByid(8);
        System.out.println(car1);
        sqlSession.close();
    }

在这里插入图片描述

只执行了一次sql语句查询。

2.2 一级缓存失效

什么情况下不走缓存?
● 第一种:不同的SqlSession对象。
● 第二种:查询条件变化了。
一级缓存失效情况包括两种:
● 第一种:第一次查询和第二次查询之间,手动清空了一级缓存。

 @Test
    public void test2() throws  Exception{
        SqlSession sqlSession = MybatisUtils.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = mapper.selectByid(8);
        System.out.println(car);
        sqlSession.clearCache();
        Car car1 = mapper.selectByid(8);
        System.out.println(car1);
        sqlSession.close();
    }

在这里插入图片描述
第二种:第一次查询和第二次查询之间,执行了增删改操作。【这个增删改和哪张表没有关系,只要有insert delete update操作,一级缓存就失效。】

 @Test
    public void test2() throws  Exception{
        SqlSession sqlSession = MybatisUtils.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = mapper.selectByid(8);
        System.out.println(car);
        mapper.InsertClazz(1003,"四班");
        Car car1 = mapper.selectByid(8);
        System.out.println(car1);
        sqlSession.close();
    }

在这里插入图片描述

3、二级缓存

3.1 开启二级缓存

二级缓存的范围是SqlSessionFactory。
使用二级缓存需要具备以下几个条件:

  1. 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。默认就是true,无需设置。
  2. 在需要使用二级缓存的SqlMapper.xml文件中添加配置:
  3. 使用二级缓存的实体类对象必须是可序列化的,也就是必须实现java.io.Serializable接口
  4. SqlSession对象关闭或提交之后,一级缓存中的数据才会被写入到二级缓存当中。此时二级缓存才可用。
    只有4个同时满足,才会开启二级缓存

Carmapper.xml

<?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">
<!--namespace先随意写一个-->
<mapper namespace="com.cky.mapper.CarMapper">
<!--    cache 表示当前配置文件 开启二级缓存-->
<cache/>
    <select id="selectByid" resultType="car">
        select * from t_car where id=#{id}
    </select>
</mapper>

CarMapper.JAVA 实现序列化接口

package com.cky.pojo;

import java.io.Serializable;

public class Car implements Serializable {
    private Integer id;
    private String carNum;
    private String brand;
    private Double guidePrice;
    private  String produceTime;
    private String carType;

    public Car(Integer id, String carNum, String brand, Double guidePrice, String produceTime, String carType) {
        this.id = id;
        this.carNum = carNum;
        this.brand = brand;
        this.guidePrice = guidePrice;
        this.produceTime = produceTime;
        this.carType = carType;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getCarNum() {
        return carNum;
    }

    public void setCarNum(String carNum) {
        this.carNum = carNum;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public Double getGuidePrice() {
        return guidePrice;
    }

    public void setGuidePrice(Double guidePrice) {
        this.guidePrice = guidePrice;
    }

    public String getProduceTime() {
        return produceTime;
    }

    public void setProduceTime(String produceTime) {
        this.produceTime = produceTime;
    }

    public String getCarType() {
        return carType;
    }

    public void setCarType(String carType) {
        this.carType = carType;
    }

    @Override
    public String toString() {
        return "Car{" +
                "id=" + id +
                ", carNum='" + carNum + '\'' +
                ", brand='" + brand + '\'' +
                ", guidePrice=" + guidePrice +
                ", produceTime='" + produceTime + '\'' +
                ", carType='" + carType + '\'' +
                '}';
    }
}

测试类

 @Test
    public void test() throws  Exception{
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();

        CarMapper mapper = sqlSession1.getMapper(CarMapper.class);
        CarMapper mapper1 = sqlSession2.getMapper(CarMapper.class);
        Car car = mapper.selectByid(7);
        System.out.println(car);
        //只有关闭sqlsession1 二级缓存才会启用,把一级缓存的内容转移到二级缓存中
        sqlSession1.close();
//        Thread.sleep(10*1000);
        //即使在sleep此期间 我通过数据库软件修改了值,但是由于此时关闭了sqlsession1 二级缓存已经启用,所以再次查询仍然会从缓存中读取,数据库中修改的数据并不会显示。
        Car car1 = mapper1.selectByid(7);
        System.out.println(car1);

        sqlSession2.close();


    }

在这里插入图片描述
第二次并没有执行sql,而是从二级缓存中读取了,因为一级缓存关闭,会将其内容保存在二级缓存中。
如果一级缓存没有关闭,二级缓存不会开启

 @Test
    public void test() throws  Exception{
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();

        CarMapper mapper = sqlSession1.getMapper(CarMapper.class);
        CarMapper mapper1 = sqlSession2.getMapper(CarMapper.class);
        Car car = mapper.selectByid(7);
        System.out.println(car);

//        Thread.sleep(10*1000);
        //即使在sleep此期间 我通过数据库软件修改了值,但是由于此时关闭了sqlsession1 二级缓存已经启用,所以再次查询仍然会从缓存中读取,数据库中修改的数据并不会显示。
        Car car1 = mapper1.selectByid(7);
        System.out.println(car1);
        //只有关闭sqlsession1 二级缓存才会启用,把一级缓存的内容转移到二级缓存中
        sqlSession1.close();
        sqlSession2.close();


    }

在这里插入图片描述
执行了两次。

3.2 二级缓存什么时候失效

进行了增删改的操作,就会导致二级缓存清空,二级缓存此时会失效。
注意:即使增删改的不是不是同一张表,但是只要是同一个sqlsessionfactory创建出来的sqlsession,进行了增删改,都会导致其失效,此时,一级缓存一定也失效

  @Test
    public void test1() throws  Exception{
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        SqlSession sqlSession3 = sqlSessionFactory.openSession();
        CarMapper mapper = sqlSession1.getMapper(CarMapper.class);
        CarMapper mapper1 = sqlSession2.getMapper(CarMapper.class);
        CarMapper mapper2 = sqlSession3.getMapper(CarMapper.class);
        Car car = mapper.selectByid(7);
        System.out.println(car);
        //只有关闭sqlsession1 二级缓存才会启用,把一级缓存的内容转移到二级缓存中
        sqlSession1.close();
        //增操作 ,失效
        int row = mapper2.InsertClazz(1002, "三班");
        sqlSession3.commit();
        System.out.println(row);
        Car car1 = mapper1.selectByid(7);
        System.out.println(car1);

        sqlSession2.close();

        sqlSession3.close();
    }
}

在这里插入图片描述

3.3 二级缓存的相关配置

在这里插入图片描述

  1. eviction:指定从缓存中移除某个对象的淘汰算法。默认采用LRU策略。
    a. LRU:Least Recently Used。最近最少使用。优先淘汰在间隔时间内使用频率最低的对象。(其实还有一种淘汰算法LFU,最不常用。)
    b. FIFO:First In First Out。一种先进先出的数据缓存器。先进入二级缓存的对象最先被淘汰。
    c. SOFT:软引用。淘汰软引用指向的对象。具体算法和JVM的垃圾回收算法有关。
    d. WEAK:弱引用。淘汰弱引用指向的对象。具体算法和JVM的垃圾回收算法有关。
  2. flushInterval:
    a. 二级缓存的刷新时间间隔。单位毫秒。如果没有设置。就代表不刷新缓存,只要内存足够大,一直会向二级缓存中缓存数据。除非执行了增删改。
  3. readOnly:
    a. true:多条相同的sql语句执行之后返回的对象是共享的同一个。性能好。但是多线程并发可能会存在安全问题。
    b. false:多条相同的sql语句执行之后返回的对象是副本,调用了clone方法。性能一般。但安全。
  4. size:
    a. 设置二级缓存中最多可存储的java对象数量。默认值1024。

4、MyBatis集成EhCache

集成EhCache是为了代替mybatis自带的二级缓存。一级缓存是无法替代的。
mybatis对外提供了接口,也可以集成第三方的缓存组件。比如EhCache、Memcache等。都可以。
EhCache是Java写的。Memcache是C语言写的。所以mybatis集成EhCache较为常见,按照以下步骤操作,就可以完成集成:
第一步:引入mybatis整合ehcache的依赖。

<!--mybatis集成ehcache的组件-->
<dependency>
  <groupId>org.mybatis.caches</groupId>
  <artifactId>mybatis-ehcache</artifactId>
  <version>1.2.2</version>
</dependency>

第二步:在类的根路径下新建echcache.xml文件,并提供以下配置信息。

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">
    <!--磁盘存储:将缓存中暂时不使用的对象,转移到硬盘,类似于Windows系统的虚拟内存-->
    <diskStore path="e:/ehcache"/>
  
    <!--defaultCache:默认的管理策略-->
    <!--eternal:设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断-->
    <!--maxElementsInMemory:在内存中缓存的element的最大数目-->
    <!--overflowToDisk:如果内存中数据超过内存限制,是否要缓存到磁盘上-->
    <!--diskPersistent:是否在磁盘上持久化。指重启jvm后,数据是否有效。默认为false-->
    <!--timeToIdleSeconds:对象空闲时间(单位:秒),指对象在多长时间没有被访问就会失效。只对eternal为false的有效。默认值0,表示一直可以访问-->
    <!--timeToLiveSeconds:对象存活时间(单位:秒),指对象从创建到失效所需要的时间。只对eternal为false的有效。默认值0,表示一直可以访问-->
    <!--memoryStoreEvictionPolicy:缓存的3 种清空策略-->
    <!--FIFO:first in first out (先进先出)-->
    <!--LFU:Less Frequently Used (最少使用).意思是一直以来最少被使用的。缓存的元素有一个hit 属性,hit 值最小的将会被清出缓存-->
    <!--LRU:Least Recently Used(最近最少使用). (ehcache 默认值).缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存-->
    <defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false"
                  timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/>

</ehcache>

第三步:修改SqlMapper.xml文件中的标签,添加type属性。

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

测试类:跟之前没区别

 @Test
    public void test() throws  Exception{
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();

        CarMapper mapper = sqlSession1.getMapper(CarMapper.class);
        CarMapper mapper1 = sqlSession2.getMapper(CarMapper.class);
        Car car = mapper.selectByid(7);
        System.out.println(car);
        sqlSession1.close();
//        Thread.sleep(10*1000);
        //即使在sleep此期间 我通过数据库软件修改了值,但是由于此时关闭了sqlsession1 二级缓存已经启用,所以再次查询仍然会从缓存中读取,数据库中修改的数据并不会显示。
        Car car1 = mapper1.selectByid(7);
        System.out.println(car1);
        //只有关闭sqlsession1 二级缓存才会启用,把一级缓存的内容转移到二级缓存中

        sqlSession2.close();


    }

在这里插入图片描述

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

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

相关文章

最齐全,最简单的免费SSL证书获取方法——实现HTTPS访问

一&#xff1a;阿里云 优势&#xff1a;大平台&#xff0c;在站长中知名度最高&#xff0c;提供20张免费单域名SSL证书 缺点&#xff1a;数量有限&#xff0c;并且只有单域名证书&#xff0c;通配符以及多域名没有免费版本。并且提供的单域名证书只有三个月的期限。 二&#…

v1.9.2-httpsok快速申请免费SSL证书

v1.9.2-&#x1f525;httpsok快速申请免费SSL证书 介绍 httpsok 是一个便捷的 HTTPS 证书自动续签工具&#xff0c;专为 Nginx 、OpenResty 服务器设计。已服务众多中小企业&#xff0c;稳定、安全、可靠。 一行命令&#xff0c;一分钟轻松搞定SSL证书自动续期 更新日志 V1…

【vue】购物车案例优化

对 购物车案例 进行优化 用watch实现全选/取消全选用watch实现全选状态的检查用computed计算总价格 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-w…

Zookeeper的集群搭建和ZAB协议详解

Zookeeper的集群搭建 1&#xff09;zk集群中的角色 Zookeeper集群中的节点有三个角色&#xff1a; Leader&#xff1a;处理集群的所有事务请求&#xff0c;集群中只有一个LeaderFollwoer&#xff1a;只能处理读请求&#xff0c;参与Leader选举Observer&#xff1a;只能处理读…

HashMap部分底层源码解析

哈希表的物理结构 HashMap底层都是哈希表&#xff08;也称散列表&#xff09;&#xff0c;线程不安全&#xff0c;其中维护了一个长度为2的幂次方的Entry类型的数组table&#xff0c;数组的每一个索引位置被称为一个桶(bucket)&#xff0c;你添加的映射关系(key,value)最终都被…

clickhouse深入浅出

基础知识原理 极致压缩率 极速查询性能 列式数据库管理 &#xff0c;读请求多 大批次更新或无更新 读很多但用很少 大量的列 列的值小数值/短字符串 一致性要求低 DBMS&#xff1a;动态创建/修改/删除库 表 视图&#xff0c;动态查/增/修/删&#xff0c;用户粒度设库…

Go——Goroutine介绍

一. 并发介绍 进程和线程 进程是程序在操作系统中一次执行过程&#xff0c;系统进程资源分配和调度的一个独立单位。线程是进程执行的实体&#xff0c;是CPU调度和分派的基本单位&#xff0c;它是比进程更小的能独立运行的基本单位。一个进程可以创建和撤销多个线程&#xff0c…

sysbench MySQL性能测试

目录 1. QPS&&TPS 1.1 数据库启动到现在的运行时间(秒) 1.2 查询量 1.3 status命令直接显示出QPS 1.4 每秒输出数据库状态(累加) 2. sysbench 测试工具 3. OLTP MySQL测试 3.1 普通参数 3.2 支持的lua脚本 3.3 脚本参数 3.4 测试数据准备 3.5 进行测试 3.…

硬件18、PCB中元器件旋转

器件旋转45度&#xff0c;如果只是用空格的话&#xff0c;器件只能旋转90度 不要用x和y&#xff0c;因为那是器件的镜像&#xff0c;但是实际器件没有镜像&#xff0c;就会导致焊接失败的问题

FPGA - 以太网UDP通信(三)

一&#xff0c;引言 前文链接&#xff1a;FPGA - 以太网UDP通信&#xff08;一&#xff09; FPGA - 以太网UDP通信&#xff08;二&#xff09; 在以上文章中介绍了以太网简介&#xff0c;以太网UDP通信硬件结构&#xff0c;以及PHY芯片RGMII接口-GMII接口转换逻辑&#xff0c…

云架构(四)异步请求-应答模式

Asynchronous Request-Reply pattern - Azure Architecture Center | Microsoft Learn 把后台处理和前端解耦&#xff0c;后台处理需要异步处理&#xff0c;但是也需要给前端一个清晰的回应。 背景和问题 在现代应用开发中&#xff0c;代码通常在浏览器中运行&#xff0c;依…

HarmonyOS实战开发-录音机、如何实现音频录制和播放的功能

介绍 本示例使用audio相关接口实现音频录制和播放的功能&#xff0c;使用mediaLibrary实现音频文件的管理。 相关概念&#xff1a; AudioRecorder&#xff1a;音频录制的主要工作是捕获音频信号&#xff0c;完成音频编码并保存到文件中&#xff0c;帮助开发者轻松实现音频录…

麒麟 V10 离线 安装 k8s 和kuboard

目录 安装文件准备 主机准备 主机配置 修改主机名&#xff08;三个节点分别执行&#xff09; 配置hosts&#xff08;所有节点&#xff09; 关闭防火墙、selinux、swap、dnsmasq(所有节点) 安装依赖包&#xff08;所有节点&#xff09; 系统参数设置(所有节点) 时间同步…

【Qt】界面优化

目录 一、QSS 1.1 基本语法 1.2 QSS设置方法 1.2.1 指定控件样式设置 1.2.2 全局样式设置 1.2.3 从文件加载样式表 1.2.4 使用Qt Designer编辑样式 1.3 选择器 1.3.1 介绍 1.3.2 子控件选择器 1.3.3 伪类选择器 1.4 样式属性(盒模型) 1.5 代码示例(登录界面) 二、…

html中的“居中”问题详解(超全)

html中的“居中”问题详解&#xff08;超全&#xff09; 图片居中文本居中定位居中元素居中响应式设计中的居中技巧 引言&#xff1a; 在网页设计和开发中&#xff0c;实现元素的居中是一个常见但也常被低估的挑战。无论是在传统的网页布局中还是在响应式设计中&#xff0c;居中…

DP10RF001一款工作于200MHz~960MHz低功耗、高性能、单片集成的(G)FSK/OOK无线收发芯片

产品概述. DP10RF001是一款工作于200MHz~960MHz范围内的低功耗、高性能、单片集成的(G)FSK/OOK无线收发机芯片。内部集成完整的射频接收机、射频发射机、频率综合器、调制解调器&#xff0c;只需配备简单、低成本的外围器件就可以获得良好的收发性能。芯片支持灵活可设的数据包…

MySQL之sql性能分析

sql执行频率 MySQL客户端连接成功后&#xff0c;通过show[session|global]status命令可以提供服务器状态信息。通过如下指令&#xff0c;可以查看当前数据库的所有INSERT、DELETE、UPDATE、SELECT的访问频次。 慢日志查询 慢查询日志记录了所有执行时间超过指定参数(longquer…

AR地图导览小程序是怎么开发出来的?

在移动互联网时代&#xff0c;AR技术的发展为地图导览提供了全新的可能性。AR地图导览小程序结合了虚拟现实技术和地图导航功能&#xff0c;为用户提供了更加沉浸式、直观的导览体验。本文将从专业性和思考深度两个方面&#xff0c;探讨AR地图导览小程序的开发方案。 编辑搜图 …

MAC系统安装PHP、Java、Python、mysql、Composer等环境无权限问题的详细操作方法说明。

本篇文章主要讲解MAC系统安装PHP、Java、Python、mysql、Composer等环境无权限问题的详细操作方法说明。通过本篇文章你可以快速掌握brew安装相对应环境的能力。 作者&#xff1a;任聪聪 日期&#xff1a;2024年4月12日 一、brew介绍及安装说明 官网地址&#xff1a;https://b…

工具推荐:市面上有哪些AI智能客服机器人比较好用?

在这个客户期望得到即时响应的时代&#xff0c;AI智能客服机器人成为了许多企业提高客户满意度和效率的重要工具。这些机器人利用最新的人工智能技术&#xff0c;可以24/7无休止地回答客户的查询&#xff0c;处理常见问题&#xff0c;甚至在必要时将问题转接给真人客服。接下来…