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

Mybatis源码(3) - Executor执行过程 | 一级缓存 | 二级缓存

      • 0. 前言:
      • 1. CachingExecutor#query:
        • 1.1. BoundSql:
        • 1.2. CacheKey:
        • 1.3. 二级缓存:
        • 1.4. 一级缓存:
      • 2. JDBC过程执行:
      • 3. 结果集处理:
      • 4. Mybatis的一级缓存、二级缓存区别:

0. 前言:

  • Mybatis源码(1) - SpringBoot整合Mybatis的核心原理  | Mybatis源码(2) - SqlSessionTemplate的介绍及创建过程
  • 之前的文章介绍之后,我们知道SQL语句最终通过DefaultSqlSession的执行器Executor进行操作,默认是CachingExecutor

在这里插入图片描述

  • 接下来看看如何进行JDBC数据库操作的

1. CachingExecutor#query:

1.1. BoundSql:

  • 自动配置的时候会将Mapper.xml的映射文件的语句解析成BoundSql封装到MappedStatement里
  • BoundSql里的SQL是已经占位符替换了的,并且记录由参数映射关系以及入参值

在这里插入图片描述

1.2. CacheKey:

  • 作为一级缓存的key,主要包含MappedStatementId,分页Offset,分页Limit,boundSql语句,sql语句参数值

在这里插入图片描述

1.3. 二级缓存:

  • 如果在Mapper.xml中配置了,也就是配置二级缓存,那么会先查二级缓存,再查一级缓存
  • 二级缓存是namespace级别,也就是Mapper级别的,默认是不开启的,也很少会用到二级缓存,就不多赘述

在这里插入图片描述

1.4. 一级缓存:

  • CachingExecutor是装饰了Executor,默认Executor的实现是BaseExecutor,针对不同场景又有三种子类,默认SimpleExecutor

在这里插入图片描述

  • BaseExecutor持有真正储存的一级缓存LocalCache(基于PerpetualCache的HasMap<CacheKey,结果List>)

在这里插入图片描述

  • 没有命中一级缓存则取去查询数据库,调用子类SimpleExecutor的doQuery实现方法

在这里插入图片描述

2. JDBC过程执行:

  • SimpleExecutor的doQuery方法,就会进行JDBC的相关操作
  • 如建立Connection,创建Statement语句,然后执行,处理结果等
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {Statement stmt = null;try {// 获取配置对象Configuration configuration = ms.getConfiguration();// 创建StatementHandler对象,实际返回的是RoutingStatementHandler对象StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);// 完成Statement的创建和初始化stmt = prepareStatement(handler, ms.getStatementLog());// 调用query方法执行sql语句,并通过ResultSetHandler完成结果集的映射return handler.query(stmt, resultHandler);} finally {// 关闭Statement对象closeStatement(stmt);}
}public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {PreparedStatement ps = (PreparedStatement) statement;//执行SQLps.execute();//处理返回结果return resultSetHandler.handleResultSets(ps);}

3. 结果集处理:

  • 根据ResultMap的类型找到对应的类型处理handler,然后根据返回结果类型调用 constructor.newInstance()创建结果对象
  • 然后解析属性名,利用反射不同字段对应的value设置到Java对象中
public List<Object> handleResultSets(Statement stmt) throws SQLException {ErrorContext.instance().activity("handling results").object(mappedStatement.getId());// 该集合用于保存映射结果得到的结果对象final List<Object> multipleResults = new ArrayList<>();int resultSetCount = 0;// 获取第一个ResultSet对象ResultSetWrapper rsw = getFirstResultSet(stmt);// 获取MappedStatement.resultMaps集合List<ResultMap> resultMaps = mappedStatement.getResultMaps();int resultMapCount = resultMaps.size();// 如果集合集不为空,则resultMaps集合不能为空,否则抛出异常validateResultMapsCount(rsw, resultMapCount);// 遍历resultMaps集合while (rsw != null && resultMapCount > resultSetCount) {// 获取该结果集对应的ResultMap对象ResultMap resultMap = resultMaps.get(resultSetCount);// 根据ResultMap中定义的映射规则对ResultSet进行映射,并将映射的结果对象添加到multipleResult集合中保存handleResultSet(rsw, resultMap, multipleResults, null);// 获取下一个结果集rsw = getNextResultSet(stmt);// 清空nestedResultObjects集合cleanUpAfterHandlingResultSet();// 递增resultSetCountresultSetCount++;}// 获取MappedStatement.resultSets属性,该属性对多结果集的情况使用,该属性将列出语句执行后返回的结果集,并给每个结果集一个名称,名称是逗号分隔的,String[] resultSets = mappedStatement.getResultSets();if (resultSets != null) {while (rsw != null && resultSetCount < resultSets.length) {// 根据resultSet的名称,获取未处理的ResultMappingResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);if (parentMapping != null) {String nestedResultMapId = parentMapping.getNestedResultMapId();ResultMap resultMap = configuration.getResultMap(nestedResultMapId);// 根据ResultMap对象映射结果集handleResultSet(rsw, resultMap, null, parentMapping);}// 获取下一个结果集rsw = getNextResultSet(stmt);// 清空nestedResultObjects集合cleanUpAfterHandlingResultSet();// 递增resultSetCountresultSetCount++;}}return collapseSingleResultList(multipleResults);
}

4. Mybatis的一级缓存、二级缓存区别:

  • 一二级缓存都是基于PerpetualCache的 HashMap 本地缓存,一级缓存是SqlSession级别的,二级缓存是Mapper(Namespace)级别
  • 默认关闭二级缓存的,但是查询的时候会先查有没有开启二级缓存,有的话先查二级缓存再查一级缓存
  • 主要实现是SqlSession持有Executor,Executor的实现BaseExecutor,持有一级缓存LocalCache
  • 然后有个CachingExecutor会装饰Executor,也就是装饰一级缓存,查询时如果开启二级缓存,CachingExecutor会通过tcm去二级缓存查询,之后再查一级缓存

相关文章:

Mybatis源码(3) - Executor执行过程 | 一级缓存 | 二级缓存

0. 前言&#xff1a;1. CachingExecutor#query&#xff1a;1.1. BoundSql&#xff1a;1.2. CacheKey&#xff1a;1.3. 二级缓存&#xff1a;1.4. 一级缓存&#xff1a;2. JDBC过程执行&#xff1a;3. 结果集处理&#xff1a;4. Mybatis的一级缓存、二级缓存区别&#xff1a;0. …...

成为 Seatunnel 源码贡献者保姆级教程

Apache SeaTunnel 是下一代高性能、分布式、海量数据集成平台&#xff0c;已经在 B 站、腾讯云等 100 家公司生产使用。目前处于 incubator 阶段。作为公司内部使用的 ETL 工具&#xff0c;Seatunnel 可以基于已有的 Spark、Flink 计算平台进行数据交换也可以运行在 k8s 平台上…...

MySQL的索引视图练习题

学生表&#xff1a;Student (Sno, Sname, Ssex , Sage, Sdept) 学号&#xff0c;姓名&#xff0c;性别&#xff0c;年龄&#xff0c;所在系 Sno为主键 课程表&#xff1a;Course (Cno, Cname,) 课程号&#xff0c;课程名 Cno为主键 学生选课表&#xff1a;SC (Sno, Cno, Score)…...

【C++ Primer Plus】第四章:复合类型

文章目录4.1 数组C11数组初始化的方法4.2 字符串**cin是如何确定已完成字符串输入呢&#xff1f;****如何每次读取一行字符串输入&#xff1f;****面向行的输入&#xff1a;getline()****面向行的输入&#xff1a;get( )****为什么推荐使用get( )&#xff0c;而不是getline( )呢…...

做外贸,你不能不懂的外贸流程知识

报关是履行海关进出境手续的必要环节之一&#xff0c;涉及两大类:进出境运输工具、物品和货物。由于性质不同&#xff0c;报关手续也有些不同。今天我就为大家详细介绍一下进出口报关的流程&#xff0c;包括出口货物报关的流程&#xff0c;随报关单提交的运费和商业单据&#x…...

日本机载激光雷达测深进展(一)日本启动测量90%沿岸水深项目

海洋地图项目利用航空测深绘制日本90%沿海20m以浅区域&#xff0c;是日本海道协会&#xff08;JHA&#xff09;和日本财团的一个联合项目。 迄今为止&#xff0c;只有不到2%的日本沿海水域得到了测绘&#xff0c;严重拖累了在海洋事故、防灾减灾、篮碳以及生物多样性保护等领域…...

MySQL数据库调优————创建索引的原则和索引失效及解决方案

创建索引的原则 建议创建索引的场景 select语句&#xff0c;频繁作为where条件的字段update/delete语句的where条件需要分组、排序的字段distinct所使用的字段字段的值有唯一性约束对于多表查询&#xff0c;联接字段应创建索引&#xff0c;且类型无比保持一致 避免隐式转换 …...

设计师都在看的全球设计网站,你居然还不知道!

设计师需要拥有无限的创意和熟练的技巧&#xff0c;并且对行业的前景和客户的心理有一定的了解。要能达到“陌生化”之前&#xff0c;肯定是有知识储备&#xff0c;专业能力的前提要求&#xff0c;以及创新能力。 今天为大家整理了多个优秀全球设计网站&#xff0c;这些博客内…...

c++:缺省参数,函数重载

今天介绍的是cpp中的缺省参数以及函数重载的知识。 首先我们先看看缺省参数&#xff1a; 缺省参数 缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时&#xff0c;如果没有指定实 参则采用该形参的缺省值&#xff0c;否则使用指定的实参。 例如&#…...

深度学习算法面试常问问题(二)

X86和ARM架构在深度学习侧的区别&#xff1f; X86和ARM架构分别应用于PC端和低功耗嵌入式设备&#xff0c;X86指令集很复杂&#xff0c;一条很长的指令就可以完成很多功能&#xff1b;而ARM指令集很精简&#xff0c;需要几条精简的短指令完成很多功能。 影响模型推理速度的因…...

美国CPC认证是什么?儿童玩具亚马逊CPC认证审核有哪些问题?

很多卖家都有遭遇listing下架&#xff0c;被要求提供CPC认证报告。这是因为亚马逊有时会加强对儿童产品的审查。本文带大家对CPC认证进行一个全面了解。什么是CPC认证&#xff1f;CPC认证&#xff0c;全称ChildrensProductCertification.是认可实验室&#xff0c;根据产品不同适…...

恭喜! SelectDB 五位开发者成为 Apache Doris 新晋 PMC 成员和 Committer!

近期&#xff0c;通过 Apache Doris 项目管理委员会的推荐与投票&#xff0c;Apache Doris 社区正式迎来了 2 位新晋 PMC 成员 和 8 位新晋 Committer 的加入。值得关注的是&#xff0c;2 位新晋 PMC 成员均来自 SelectDB&#xff0c;分别是衣国垒&#xff08;yiguolei&#xf…...

数据库面试题

第一范式&#xff08;1NF&#xff09; 第一范式是指数据库的每一列都是不可分割的基本数据项&#xff0c;而下面这样的就存在可分割的情况&#xff1a; 学生&#xff08;姓名&#xff0c;电话号码&#xff09; 电话号码实际上包括了家用座机电话和移动电话&#xff0c;因此它…...

[USACO2022-DEC-Bronze] T2 Feeding the Cows 题解

一、题目描述Farmer John has N (1≤N≤10^5) cows, the breed of each being either a Guernsey or a Holstein. They have lined up horizontally with the cows occupying positions labeled from 1…N.Farmer John 有 N&#xff08;1≤N≤105&#xff09;头奶牛&#xff0c…...

Unity法线贴图原理理解(为什么存在切线空间?存的值是什么?)

Unity法线贴图原理理解(为什么存在切线空间&#xff1f;存的值是什么&#xff1f;&#xff09;写在前面1、为什么用法线贴图&#xff1f;2、用什么存法线&#xff1f;3、法线向量为什么存在切线空间&#xff1f;法线贴图存得是什么&#xff1f;4、法线贴图为什么会偏蓝&#xf…...

【JavaWeb】传输层协议——UDP + TCP

目录 UDP协议 UDP协议结构 UDP的特点 TCP协议 TCP协议结构 TCP的特点 TCP的十个核心机制 确认应答 超时重传 连接管理 滑动窗口 流量控制 阻塞控制 延迟应答 捎带应答 粘包问题 异常处理 UDP协议 UDP协议结构 源端口&#xff1a;存储的是发送方的端口号。 目的…...

C++ 中是用来修饰:内置类型变量、自定义对象、成员函数、返回值、函数参数

const 是 constant 的缩写&#xff0c;本意是不变的&#xff0c;不易改变的意思。在 C 中是用来修饰内置类型变量&#xff0c;自定义对象&#xff0c;成员函数&#xff0c;返回值&#xff0c;函数参数。 一. const修饰 普通类型的变量 const int a 7; int b a; // 正确 …...

av 146 002

61. 一个新的敏捷项目经理正试图确定团队该如何执行一个发布计划的进度。哪种工具可以更深入地了解团队的进展? A. 发布计划系统 B. 产品路线图。 C. 看板。 D. 燃尽图 62. 你的项目发起人找到你&#xff0c;让你知道他正在考虑给你项目中的一位高级工程师颁发1000美元的现…...

小红书用户画像 | 小红书数据平台

小红书的用户画像是小红书品牌营销的必备技能&#xff0c;也是小红书推广种草的一个重要前提。通过对小红书用户画像进行分析&#xff0c;对品牌进行精准营销&#xff0c;实现更高的流量转化。 2022小红书粉丝人群画像 千瓜数据在2022年发布的千瓜活跃用户画像趋势报告中分析了…...

【STM32笔记】低功耗模式下GPIO、外设、时钟省电配置避坑

【STM32笔记】低功耗模式下GPIO、外设、时钟省电配置避坑 前文&#xff1a; blog.csdn.net/weixin_53403301/article/details/128216064 【STM32笔记】HAL库低功耗模式配置&#xff08;ADC唤醒无法使用、低功耗模式无法烧录解决方案&#xff09; blog.csdn.net/weixin_534033…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

android13 app的触摸问题定位分析流程

一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...