MyBatis 缓存的使用,看这篇就够了
wxin55 2024-11-24 22:36 11 浏览 0 评论
在日常工作中,我们大多使用MyBatis的默认缓存配置,但是MyBatis缓存机制也有一些不足之处,一不留神就会出现脏数据,形成一些潜在的隐患,后续排查问题容易浪费时间精力。
所以,如何用好MyBatis的缓存,是重中之重的。这里主要介绍MyBatis 的一级缓存和二级缓存。
在默认的情况下, 只开启一级缓存(一级缓存是对同一个 SqlSession 而言的)。
1 一级缓存
同一个 SqlSession 对象, 在参数和 SQL 完全一样的情况下, 只执行一次 SQL 语句(如果缓存没有过期) 也就是只有在参数和SQL 完全一样的情况下, 才会有这种情况。
原理图如下:一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构用于存储缓存数据。不同的sqlSession之间的缓存数据区域是互相不影响的。也就是他只能作用在同一个sqlSession中,不同的sqlSession中的缓存是互相不能读取的。
1.1 同一个 SqlSession
在以上的代码中, 进行了两次查询, 使用相同的 SqlSession, 结果如下
在日志和输出中:第一次查询发送了 SQL 语句, 后返回了结果;第二次查询没有发送 SQL 语句, 直接从内存中获取了结果。而且两次结果输入一致, 同时断言两个对象相同也通过。
1.2 不同的 SqlSession
在代码中, 分别使用 sqlSession 和 sqlSession2 进行了相同的查询。其结果如下
从日志中可以看到两次查询都分别从数据库中取出了数据。 虽然结果相同, 但两个是不同的对象。
1.3 刷新缓存
刷新缓存是清空这个 SqlSession 的所有缓存, 不单单是某个键。
如果是以上, 没什么不同, 结果还是第二个不发 SQL 语句。在此, 做一些修改, 在 StudentMapper.xml 中, 添加
修改后的配置文件如下:
结果如下:
第一次, 第二次都发送了 SQL 语句, 同时, 断言两个对象相同出错。
1.4 总结
在同一个 SqlSession 中, MyBatis 会把执行的方法和参数通过算法生成缓存的键值, 将键值和结果存放在一个 Map 中, 如果后续的键值一样, 则直接从 Map 中获取数据;
不同的 SqlSession 之间的缓存是相互隔离的;
用一个 SqlSession, 可以通过配置使得在查询前清空缓存;
任何的 UPDATE, INSERT, DELETE 语句都会清空缓存。
2 二级缓存
二级缓存存在于 SqlSessionFactory 生命周期中。二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。UserMapper有一个二级缓存区域(按namespace分),其它mapper也有自己的二级缓存区域(按namespace分)。每一个namespace的mapper都有一个二级缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同的二级缓存区域中。
2.1 配置二级缓存
2.1.1 全局开关
在 MyBatis 中, 二级缓存有全局开关和分开关, 全局开关, 在 MyBatis-config.xml 中如下配置:
默认是为 true, 即默认开启总开关。
2.1.2 分开关
分开关就是说在 *Mapper.xml 中开启或关闭二级缓存, 默认是不开启的。
2.1.3 entity 实现序列化接口
2.2 使用二级缓存
结果如下:
以上结果, 分几个过程解释:第一阶段:
在第一个 SqlSession 中, 查询出 student 对象, 此时发送了 SQL 语句;
student更改了name 属性;
SqlSession 再次查询出 student1 对象, 此时不发送 SQL 语句, 日志中打印了 「Cache Hit Ratio」, 代表二级缓存使用了, 但是没有命中。 因为一级缓存先作用了。
由于是一级缓存, 因此, 此时两个对象是相同的。
调用了 sqlSession.close(), 此时将数据序列化并保持到二级缓存中。
第二阶段:
新创建一个 sqlSession.close() 对象;
查询出 student2 对象,直接从二级缓存中拿了数据, 因此没有发送 SQL 语句, 此时查了 3 个对象,但只有一个命中, 因此 命中率 1/3=0.333333;
查询出 student3 对象,直接从二级缓存中拿了数据, 因此没有发送 SQL 语句, 此时查了 4 个对象,但只有一个命中, 因此 命中率 2/4=0.5;
由于 readOnly=“false”, 因此 student2 和 student3 都是反序列化得到的, 为不同的实例。
看到这里的小伙伴,如果你喜欢这篇文章的话,别忘了转发、收藏、留言互动!
如果对文章有任何问题,欢迎在留言区和我交流~
最近我新整理了一些资料,包含面经分享、模拟试题、和视频干货,如果你需要的话,欢迎私信我!
相关推荐
- ES6中 Promise的使用场景?(es6promise用法例子)
-
一、介绍Promise,译为承诺,是异步编程的一种解决方案,比传统的解决方案(回调函数)更加合理和更加强大在以往我们如果处理多层异步操作,我们往往会像下面那样编写我们的代码doSomething(f...
- JavaScript 对 Promise 并发的处理方法
-
Promise对象代表一个未来的值,它有三种状态:pending待定,这是Promise的初始状态,它可能成功,也可能失败,前途未卜fulfilled已完成,这是一种成功的状态,此时可以获取...
- Promise的九大方法(promise的实例方法)
-
1、promise.resolv静态方法Promise.resolve(value)可以认为是newPromise方法的语法糖,比如Promise.resolve(42)可以认为是以下代码的语...
- 360前端一面~面试题解析(360前端开发面试题)
-
1.组件库按需加载怎么做的,具体打包配了什么-按需加载实现:借助打包工具(如Webpack的require.context或ES模块动态导入),在使用组件时才引入对应的代码。例如在V...
- 前端面试-Promise 的 finally 怎么实现的?如何在工作中使用?
-
Promise的finally方法是一个非常有用的工具,它无论Promise是成功(fulfilled)还是失败(rejected)都会执行,且不改变Promise的最终结果。它的实现原...
- 最简单手写Promise,30行代码理解Promise核心原理和发布订阅模式
-
看了全网手写Promise的,大部分对于新手还是比较难理解的,其中几个比较难的点:状态还未改变时通过发布订阅模式去收集事件实例化的时候通过调用构造函数里传出来的方法去修改类里面的状态,这个叫Re...
- 前端分享-Promise可以中途取消啦(promise可以取消吗)
-
传统Promise就像一台需要手动组装的设备,每次使用都要重新接线。而Promise.withResolvers的出现,相当于给开发者发了一个智能遥控器,可以随时随地控制异步操作。它解决了三大...
- 手写 Promise(手写输入法 中文)
-
前言都2020年了,Promise大家肯定都在用了,但是估计很多人对其原理还是一知半解,今天就让我们一起实现一个符合PromiseA+规范的Promise。附PromiseA+规范地址...
- 什么是 Promise.allSettled()!新手老手都要会?
-
Promise.allSettled()方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的pr...
- 前端面试-关于Promise解析与高频面试题示范
-
Promise是啥,直接上图:Promise就是处理异步函数的API,它可以包裹一个异步函数,在异步函数完成时抛出完成状态,让代码结束远古时无限回掉的窘境。配合async/await语法糖,可...
- 宇宙厂:为什么前端离不开 Promise.withResolvers() ?
-
大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发。1.为什么需要Promise.with...
- Promise 新增了一个超实用的 API!
-
在JavaScript的世界里,Promise一直是处理异步操作的神器。而现在,随着ES2025的发布,Promise又迎来了一个超实用的新成员——Promise.try()!这个新方法简...
- 一次搞懂 Promise 异步处理(promise 异步顺序执行)
-
PromisePromise就像这个词的表面意识一样,表示一种承诺、许诺,会在后面给出一个结果,成功或者失败。现在已经成为了主流的异步编程的操作方式,写进了标准里面。状态Promise有且仅有...
- Promise 核心机制详解(promise机制的实现原理)
-
一、Promise的核心状态机Promise本质上是一个状态机,其行为由内部状态严格管控。每个Promise实例在创建时处于Pending(等待)状态,此时异步操作尚未完成。当异步操作成功...
- javascript——Promise(js实现promise)
-
1.PromiseES6开始支持,Promise对象用于一个异步操作的最终完成(包括成功和失败)及结果值的表示。简单说就是处理异步请求的。之所以叫Promise,就是我承诺,如果成功则怎么处理,失败怎...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- ES6中 Promise的使用场景?(es6promise用法例子)
- JavaScript 对 Promise 并发的处理方法
- Promise的九大方法(promise的实例方法)
- 360前端一面~面试题解析(360前端开发面试题)
- 前端面试-Promise 的 finally 怎么实现的?如何在工作中使用?
- 最简单手写Promise,30行代码理解Promise核心原理和发布订阅模式
- 前端分享-Promise可以中途取消啦(promise可以取消吗)
- 手写 Promise(手写输入法 中文)
- 什么是 Promise.allSettled()!新手老手都要会?
- 前端面试-关于Promise解析与高频面试题示范
- 标签列表
-
- hive行转列函数 (63)
- sourcemap文件是什么 (54)
- display none 隐藏后怎么显示 (56)
- 共享锁和排他锁的区别 (51)
- httpservletrequest 获取参数 (64)
- jstl包 (64)
- qsharedmemory (50)
- watch computed (53)
- java中switch (68)
- date.now (55)
- git-bash (56)
- 盒子垂直居中 (68)
- npm是什么命令 (62)
- python中+=代表什么 (70)
- fsimage (51)
- nginx break (61)
- mysql分区表的优缺点 (53)
- centos7切换到图形界面 (55)
- 前端深拷贝 (62)
- kmp模式匹配算法 (57)
- jsjson字符串转json对象 (53)
- jdbc connection (61)
- javascript字符串转换为数字 (54)
- mybatis 使用 (73)
- 安装mysql数据库 (55)