MyBatis一级缓存和二级缓存

news2024/11/24 3:57:15

缓存的作用

在 Web 系统中,最重要的操作就是查询数据库中的数据。但是有些时候查询数据的频率非常高,这是很耗费数据库资源的,往往会导致数据库查询效率极低,影响客户的操作体验。于是可以将一些变动不大且访问频率高的数据,放置在一个缓存容器中,用户下一次查询时就从缓存容器中获取结果。

MyBatis 的缓存结构

MyBatis 系统中默认定义了两级缓存:一级缓存和二级缓存:

MyBatis 一级缓存是一个 SqlSession 级别,Sqlsession 只能访问自己的一级缓存的数据。

二级缓存是跨 sqlSession,是 mapper 级别的缓存,对于 mapper 级别的缓存不同的 sqlsession 是可以共享的。

MyBatis 默认开启一级缓存,同时为了增强扩展性,MyBatis 定义了缓存接口 Cache,可以通过 Cache 自定义二级缓存。

一级缓存

MyBatis 一级缓存是一个 SqlSession 级别的缓存,缓存的执行遵循下方的规则:

  1. 映射语句文件中的所有 select 语句的结果将会被缓存。

  2. 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。

  3. 缓存默认会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。

  4. 缓存不会定时进行刷新(也就是说,没有刷新间隔)。

  5. 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。

  6. 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

接下来通过代码模拟一级缓存的执行,用的代码是最简单的一个用户类,首先第一步在 mybatis-config 中开启 log 日志:

<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

编写测试代码,在同样的查询条件下查询第二次:

public class CacheTest1 {

    public static void main(String[] args) {
        // 获取SqlSession
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        // 执行Sql
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user=mapper.getUserById(1);
        System.out.println(user);
        //同样的条件查询第二次
        User user2=mapper.getUserById(1);
        System.out.println(user2);
        sqlSession.close();
    }
}

在这里插入图片描述
首先这段代码是在一个 SqlSession 下,因此默认开启了一级缓存,在结果中可以看到,第一次查询走的是数据库,第二次就不需要再查数据库了。满足第一条规则:

映射语句文件中的所有 select 语句的结果将会被缓存。

修改条件,在查询第二次之前先往表里插入一条数据:

public class CacheTest2 {

    public static void main(String[] args) {
        // 获取SqlSession
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        // 执行Sql
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user=mapper.getUserById(1);
        System.out.println(user);

        //第二次查询前先插入一条数据
        User user1=new User(5,"java");
        mapper.insertUser(user1);

        //同样的条件查询第二次
        User user2=mapper.getUserById(2);
        System.out.println(user2);
        sqlSession.close();
    }
}

在这里插入图片描述

在第一次查询之后插入了一条数据,第二次同样条件查询时没有走缓存,再次查表,符合规则:

映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。

二级缓存

二级缓存的作用域比一级缓存要更大,二级缓存是 mapper 级别的缓存,你也可以理解为他是一个 namespace 内的缓存。

开启二级缓存需要几个步骤:

1、 MyBatis 中开启缓存需要首先在设置中开启 cacheEnabled

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

cacheEnabled 默认也是开启状态。

2、 在 mapper.xml 中使用二级缓存

在 UserMapper.xml 文件的 mapper 节点下增加一行 , 这个 mapper 就开启了二级缓存。

MyBatis 缓存要求对应的对象需要实现序列话,因此给 User 对象加上序列化

import java.io.Serializable;

public class User implements Serializable{
    private static final long serialVersionUID = 1L;
    private int id;
    private String name;
    public User(){}
    public User(int id,String name){
        this.id=id;
        this.name=name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    @Override
    public String toString() {
        return "id:"+this.id+" name:"+this.name;
    }
}

编写测试用例,下面这段代码在第一次查询结束后关闭了 SqlSession,接着重新生成一个 SqlSession 执行第二次查询,一级缓存就没有用了,这样的场景下就需要二级缓存。

public class CacheTest3 {

    public static void main(String[] args) {
        // 获取SqlSession
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        // 执行Sql
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user=mapper.getUserById(1);
        System.out.println(user);
        // 第一次查询结束后关闭 SqlSession
        sqlSession.close();
        sqlSession = MyBatisUtils.getSqlSession();
        // 执行Sql
        mapper = sqlSession.getMapper(UserMapper.class);
        //同样的条件查询第二次
        User user2=mapper.getUserById(1);
        System.out.println(user2);
        sqlSession.close();
    }
}

在这里插入图片描述
使用 useCache 对具体某一个查询设置不适用缓存:

<select id="getUserById" resultMap="UserMap" parameterType="int" useCache="false">
    select id,name from user where id=#{id};
</select>

cache 标签可以通过配置进行修改:

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

重点讲一下清除策略(eviction):

  1. LRU – 最近最少使用:移除最长时间不被使用的对象。

  2. FIFO – 先进先出:按对象进入缓存的顺序来移除它们。

  3. SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。

  4. WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。

这里主要了解 LRU 和 FIFO 即可,默认的清除策略是 LRU。

其他几个属性的配置如下:

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

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

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

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

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

相关文章

六、Java 13 新特性

六、Java 13 新特性 Java 13 已如期于 9 月 17 日正式发布&#xff0c;此次更新是继半年前 Java 12 这大版本发布之后的一次常规版本更新&#xff0c;在这一版中&#xff0c;主要带来了 ZGC 增强、更新 Socket 实现、Switch 表达式更新等方面的改动、增强。本文主要针对 Java 1…

开发检查测试参考文档整理

前言 【1】比起成为一名优秀的程序员&#xff0c;我更青睐于成为一名有价值的靠谱的员工。在企业工作中&#xff0c;我们既需要很好的去完成我们的日常需求&#xff0c;同时也需要去保证我们编写代码的质量&#xff0c;减少问题的发生&#xff0c;我们要去做靠谱的有责任心的员…

【Arduino串口数据保存到excel中常用三种方法】

【Arduino串口数据保存到excel中常用三种方法】 1. 前言2. 利用excel自带Data Streamer读取2.1 启用 Data Streamer 加载项2.2 刷写代码并将微控制器连接到你的电脑2.3 excel画图记录3. 采用插件ArduSpreadsheet读取3.1 安装ArduSpreadsheet3.2 Arduino 代码4. python代码解析4…

pyTorch入门(五)——训练自己的数据集

学更好的别人&#xff0c; 做更好的自己。 ——《微卡智享》 本文长度为1749字&#xff0c;预计阅读5分钟 前言 前面四篇将Minist数据集的训练及OpenCV的推理都介绍完了&#xff0c;在实际应用项目中&#xff0c;往往需要用自己的数据集进行训练&#xff0c;所以本篇就专门介绍…

UCOS-III任务堆栈溢出检测及统计任务堆栈使用量的方法

1、说在前 在操作系统任务设计的时候&#xff0c;通常会遇到一个比较麻烦的问题&#xff0c;也就是任务堆栈大小设定的问题&#xff0c;为此我们我需要知道一些问题&#xff1a; 1.1. 任务堆栈一但溢出&#xff0c;意味着系统的崩溃&#xff0c;在有MMU或者MPU的系统中&#xf…

linux centons安装cpolar内网穿透

Linux操作系统在个人电脑上并不多见&#xff0c;但在需要集中资源处理信息交互的服务器上&#xff0c;Linux系统却几乎是唯一的存在。而cpolar凭借极极低的资源占用和便捷操作&#xff0c;十分适合在linux系统上使用。今天&#xff0c;我们就为大家介绍&#xff0c;如何在linux…

判断变量是否为数组及通用判断数据类型方法

判断变量是不是数组类型 function fn() {console.log(Array.isArray(arguments)); //false; 因为arguments是类数组&#xff0c;但不是数组console.log(Array.isArray([1,2,3,4])); //trueconsole.log(arguments instanceof Array); //fasleconsole.log([1,2,3,4] instance…

python中利用tkinter和ImageTK进行圣诞快乐图片的显示

一、前言 python中使用tkinter加载“Merry Christmas“ 图片。 二、用python显示Merry Christmas图片 1. python中&#xff0c;tkinter中可以进行图形界面编程。tkinter库提供了各种控件&#xff0c;其中&#xff0c;可以使用PhotoImage和Label组合&#xff0c;进行“Merry Chr…

【树莓派不吃灰】网络篇 Tcpdump iptables

目录1、一台主机上只能保持最多 65535 个 TCP 连接吗&#xff1f;2、tcpdump3、iptables❤️ 博客主页 单片机菜鸟哥&#xff0c;一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2022-12-26 ❤️❤️ 本篇更新记录 2022-12-26 ❤️&#x1f389; 欢迎关注 &#x1f50e;点…

RT-Thread 学习笔记(十四)--- 开启基于RTGUI的LCD显示功能(4)<demo组件的按键响应和焦点支持>

软件环境&#xff1a;Win7&#xff0c;Keil MDK 4.72a, IAR EWARM 7.2, GCC 4.2&#xff0c;Python 2.7 ,SCons 2.3.2 硬件环境&#xff1a;Armfly STM32F103ZE-EK v3.0开发板 参考文章&#xff1a;RT-Thread编程指南 RT-Thread_1.2.0lwiprtgui0.8.0 移植心得 RT-Thread RT…

2022/12/26 请你谈谈数据库事务机制?

1 事务四大特征 一般来说&#xff0c;事务是必须满足4个条件&#xff08;ACID&#xff09;&#xff1a;原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔离性&#xff08;Isolation&#xff09;、持久性&#xff08;Durability&#…

软件测试工程职场发展细谈

前言 今天几个测试圈子的大佬约了饭局&#xff0c;席间彼此交流了很多关于职场工作上测试相关的话题&#xff0c;听了他们的一些观点很有启发&#xff0c;我自己对于聊的话题也做了一些描述和实际的案例说明。下面是聊的一些关键话题&#xff0c;我将交流的内容和个人观点整理…

(二)JavaScript

JavaScript 是一门跨平台、面向对象的脚本语言。JavaScript 是用来控制网页行为的&#xff0c;它能使网页可交互。 一、JavaScript 引入方式&#xff08;P71&#xff09; &#xff08;1&#xff09;内部脚本&#xff1a;将JS代码定义在HTML页面中 &#xff08;2&#xff09;外部…

ActiveMQ集群模式

目录 一、面试题 二、多节点集群是什么 三、zookeeperreplicated-leveldb-store的主从集群 四、官网集群原理图 五、部署规划和步骤 六、集群可用性测试 一、面试题 引入消息队列之后该如何保证其高可用性 二、多节点集群是什么 基于ZooKeeper和LevelDB搭建ActiveMQ 集…

API签名鉴权设计

鉴权作用 在实际的业务中&#xff0c;必然会存在和其他平台系统进行数据传输。这个时候出于对数据的保密要求&#xff0c;都会对接口&#xff08;API&#xff09;添加鉴权机制&#xff0c;识别调用方的真实身份&#xff0c;对未通过鉴权的请求不做任何业务处理&#xff0c;以帮…

国科大模式识别导论作业3:神经网络

目录题目代码data.pyutils.pynetwork.pymain.py结果整理一下近期作业中的编程题&#xff0c;仅供交流学习题目 本题使用的数据如下&#xff1a; 第一类 10 个样本&#xff08;三维空间&#xff09;&#xff1a; [ 1.58, 2.32, -5.8], [ 0.67, 1.58, -4.78], [ 1.04, 1.01, -3…

OpenCV 图像旋转、平移、缩放

本文是 OpenCV图像视觉入门之路的第7篇文章&#xff0c;本文详细的进行了图像的缩放 cv2.resize()、旋转 cv2.flip()、平移 cv2.warpAffine()等操作。 OpenCV 图像旋转、平移、缩放目录 1 缩放图片 2 翻转图片 2.1 垂直翻转 2.2 水平翻转 2.3 水平垂直翻转 ​编辑 3 平移…

百度离线人脸识别SDK

1&#xff0c;采坑备忘 &#xff08;1&#xff09;8.1版本的SDK在spring-boot接口访问第一次正常&#xff0c;第二次之后JVM会奔溃&#xff0c;可能是java gc 处理C开出的内存有问题。 换6.1.3版本的SDK。 javaWindows百度离线人脸识别SDK6.1.3-Java文档类资源-CSDN下载javaW…

Harmony/OpenHarmony应用开发-转场动画页面间转场

在全局pageTransition方法内配置页面入场和页面退场时的自定义转场动效。 说明&#xff1a;从API Version 7开始支持。开发语言ets. 名称 参数 参数描述 PageTransitionEnter { type: RouteType, duration: number, curve: Curve | string, delay: number } 设置当前页面…

1998-2014年企业绿色发展数据库

1998-2014年工业企业的排放排污和环境治理等信息数据 1、时间&#xff1a;1998-2014年 2、数据来源&#xff1a;原环保部。 3、统计字段&#xff1a;主要有企业基本信息、生产信息、水环境、大气环境&#xff0c;内容涵盖了资源利用类指标&#xff08;工业用水量、煤炭消费量…