当前位置: 首页 > news >正文

Mybatis缓存机制(图文并茂!)

目录

一级缓存 

需求我们在一个测试中通过ID两次查询Monster表中的信息。 

二级缓存

案例分许(和上述一样的需求)

EhCache第三方缓存


在了解缓存机制之前,我们要先了解什么是缓存:

缓存是一种高速存储器,用于暂时存储访问频繁的数据,以提高数据存取速度。

所以,缓存的目的就是用来提高检索的效率

在mybatis中我们是尽量避免java和DB的直接操作的,因为本质上他是一个网络操作,包括建立连接,释放连接等,效率很低,耦合性高,所以在java程序和数据库db之间有一个缓存机制,db数据库会首先将查询的数据放入缓存,下一次要用时,java程序会直接从缓冲中取,效率和速度都会大大的提高!

文档地址:mybatis – MyBatis 3 | XML 映射器


一级缓存 

1. 默认情况下, mybatis 是启用一级缓存的也就是 本地缓存 /local Cache ,它是 SqlSession 级别的。
2. 同一个 SqlSession 接口对象调用了相同的 select 语句 , 会直接从缓存里面获取,而不是再 去查询数据库。
3. 当我们执行 sqlSession.clearCache(); 会使一级缓存失效

 

需求我们在一个测试中通过ID两次查询Monster表中的信息。 


二级缓存

1. 二级缓存和一级缓存都是为了提高检索效率的技术
2. 最大的区别就是作用域的范围不一样,一级缓存的作用域是 sqlSession 会话级别,在一次

会话有效,而二级缓存作用域是全局范围,针对不同的会话都有效(就是在一个sqlsession和在多个sqlsession生效的区别)

二级缓存大致的工作原理:

当java程序像数据库申请数据时,首先执行的是CachingExecutor缓存执行器(默认是关闭二级缓存的),先去二级缓存中查找数据(这是mybatis自带的 ,也可以采用第三方的缓存库),如果查不到,就调用Executor去查询本地的缓存,也就是一级缓存。在查不到,就去DB中查找数据 

 

案例分许(和上述一样的需求)

1.首先在mybatis-config中配置映射缓存(默认是打开的)

2.使用二级缓存时 entity 类实现序列化接口 (serializable),因为二级缓存可能使用到序列化技术

 因为比如一些三方缓存,一级缓存是在内存中的,二级缓存要将其存在磁盘中,在java中奖对象保存在磁盘中就需要用到序列化技术

3. 在对应的 XxxMapper.xml 中设置二级缓存的策略 

1. 理解二级缓存策略的参数
<cache eviction="FIFO" flushInterval="30000" size="360" readOnly="true"/>
上面的配置意思如下:
创建了 FIFO 的策略,每隔 30 秒刷新一次,最多存放 360 个对象而且返回的对象被认为是
只读的。
eviction:缓存的回收策略
flushInterval:时间间隔,单位是毫秒,
size:引用数目,内存大就多配置点,要记住你缓存的对象数目和你运行环境的可用内存
资源数目。默认值是 1024
readOnly:true,只读
2. 四大策略

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

可以在XML文件中配置这些属性(下面给大家解释)

 

 测试结果

    @Test
public void test02()
{Monster monsterById = monsterMapper.getMonsterById(1);System.out.println(monsterById);if(sqlSession != null){sqlSession.close();}System.out.println("因为开启了二级缓存,将sqlSession关闭,第二次存入二级缓存" +"中依然不会再次发送SQL语句");//此时的sqlSession是不一样的sqlSession了sqlSession = MyBatisUtils.getSqlSession();//获取MonsterMapper对象(通过类型获取对象)monsterMapper = sqlSession.getMapper(MonsterMapper.class);Monster monsterById2 = monsterMapper.getMonsterById(1);System.out.println(monsterById2);if(sqlSession != null){sqlSession.close();}
}

 

 我们如果需要指定哪些方法需要用二级缓存,可以进行参数的指定


EhCache第三方缓存

配置文档 : https://www.cnblogs.com/zqyanywn/p/10861103.html
1. EhCache 是一个纯 Java 的缓存框架,具有快速、精干等特点
2. MyBatis 有自己默认的二级缓存 ( 前面我们已经使用过了 ) ,但是在实际项目中,往往使用
的是更加专业的第三方缓存产品 作为 MyBatis 的二级缓存 ,EhCache 就是非常优秀的缓存
产品

1.在pom.xml文件中加入相关的依赖

    <dependencies>
<!--引入EhCache--><dependency><groupId>net.sf.ehcache</groupId><artifactId>ehcache-core</artifactId><version>2.6.11</version></dependency>
<!--引入slf4j日志输出jar包--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.25</version></dependency>
<!--引入将mybatis和EhCache整合的jar包--><dependency><groupId>org.mybatis.caches</groupId><artifactId>mybatis-ehcache</artifactId><version>1.2.1</version></dependency></dependencies>

2. mybatis-config.xml中 打开二级缓存

3.在resource下配置ehcache.xml配置文件(直接copy上去就行)

一些配置参数的文档说明: https://www.taobye.com/f/view-11-23.html

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="https://ehcache.org/ehcache.xsd"updateCheck="false"><!--diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下:user.home – 用户主目录user.dir  – 用户当前工作目录java.io.tmpdir – 默认临时文件路径--><diskStore path="java.io.tmpdir/Tmp_EhCache"/><!--defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。--><!--name:缓存名称。maxElementsInMemory:缓存最大数目maxElementsOnDisk:硬盘最大缓存个数。eternal:对象是否永久有效,一但设置了,timeout将不起作用。overflowToDisk:是否保存到磁盘,当系统当机时timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。clearOnFlush:内存数量最大时是否清除。memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。FIFO,first in first out,这个是大家最熟的,先进先出。LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。--><defaultCacheeternal="false"maxElementsInMemory="10000"overflowToDisk="false"diskPersistent="false"timeToIdleSeconds="1800"timeToLiveSeconds="259200"memoryStoreEvictionPolicy="LRU"/><cachename="cloud_user"eternal="false"maxElementsInMemory="5000"overflowToDisk="false"diskPersistent="false"timeToIdleSeconds="1800"timeToLiveSeconds="1800"memoryStoreEvictionPolicy="LRU"/></ehcache>
4. XxxMapper.xml 中启用 EhCache , 当然原来 MyBatis 自带的缓存配置就注销了
< cache type ="org.mybatis.caches.ehcache.EhcacheCache" />
使用测试时,你用二级缓存的测试结果都一样。表现出来的效果差不多。
如何理解 EhCache 和 MyBatis 缓存的关系
1. MyBatis 提供了一个接口 Cache
2. 只要实现了该 Cache 接口,就可以作为二级缓存产品和 MyBatis 整合使用 ,Ehcache
是实现了该接口
3. MyBatis 默认情况 ( 即一级缓存 ) 是使用的 PerpetualCache 类实现 Cache 接口的 , 是核心类
4.当我们使用了 Ehcahce 后,就是 EhcacheCache 类实现 Cache 接口的,是核心类 .

相关文章:

  • 雷池 WAF 如何配置才能正确获取到源 IP
  • Python中requests模块(爬虫)基本使用
  • MySQL的驱动安装
  • OpenCV-图像拼接
  • Python爬虫爬取王者荣耀英雄信息并保存到图数据库
  • Spring源码学习:SpringMVC(2)DispatcherServlet初始化【子容器9大组件】
  • 【YOLO目标检测车牌数据集】共10000张、已标注txt格式、有训练好的yolov5的模型
  • python中logging的用法
  • 433按键单片机解码
  • Meta AI 发布 Llama 3.2
  • 赛氪作媒体支持单位受邀参加首届科普翻译与跨学科专业学术研讨会
  • OCR Fusion: EasyOCR/Tesseract/PaddleOCR/TrOCR/GOT
  • 不同的浏览器、服务器和规范对 URL 长度的限制
  • 前端面试经验总结2(经典问题篇)
  • LIMS和LIS的主要区别
  • CSS魔法堂:Absolute Positioning就这个样
  • Go 语言编译器的 //go: 详解
  • HTTP请求重发
  • JavaScript-Array类型
  • JavaScript函数式编程(一)
  • PAT A1017 优先队列
  • redis学习笔记(三):列表、集合、有序集合
  • SpringBoot 实战 (三) | 配置文件详解
  • supervisor 永不挂掉的进程 安装以及使用
  • 初探 Vue 生命周期和钩子函数
  • 从伪并行的 Python 多线程说起
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 配置 PM2 实现代码自动发布
  • 入门级的git使用指北
  • 无服务器化是企业 IT 架构的未来吗?
  • # Apache SeaTunnel 究竟是什么?
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (2)从源码角度聊聊Jetpack Navigator的工作流程
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (苍穹外卖)day03菜品管理
  • (欧拉)openEuler系统添加网卡文件配置流程、(欧拉)openEuler系统手动配置ipv6地址流程、(欧拉)openEuler系统网络管理说明
  • (四)事件系统
  • (转)VC++中ondraw在什么时候调用的
  • **python多态
  • .NET Core中的去虚
  • .net FrameWork简介,数组,枚举
  • .NET微信公众号开发-2.0创建自定义菜单
  • .NET中的Exception处理(C#)
  • /bin/bash^M: bad interpreter: No such file ordirectory
  • @Tag和@Operation标签失效问题。SpringDoc 2.2.0(OpenApi 3)和Spring Boot 3.1.1集成
  • @我的前任是个极品 微博分析
  • [AMQP Connection 127.0.0.1:5672] An unexpected connection driver error occured
  • [Android] Upload package to device fails #2720
  • [bzoj 3124][sdoi 2013 省选] 直径
  • [BZOJ1040][P2607][ZJOI2008]骑士[树形DP+基环树]
  • [C++内存管理]new,delete,operator new,opreator delete
  • [Doc][ROS2]订阅发布、服务客户端区别
  • [Flutter]设置应用包名、名称、版本号、最低支持版本、Icon、启动页以及环境判断、平台判断和打包
  • [JAVA数组] 三个数的最大乘积