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

MyBatis执行一条sql语句的流程(源码解析)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

MyBatis执行一条sql语句的流程(源码解析)

  • MyBatis执行sql语句的流程
  • 加载配置文件
    • 加载配置文件的流程
  • 创建sqlsessionFactory对象
    • 解析Mapper
    • 创建sqlsessionFactory流程
  • 获取sqlsession
  • 创建mapper代理
  • 执行mapper方法
  • 总结:MyBatis执行一条sql语句的流程


MyBatis执行sql语句的流程

    //<1> 加载配置文件InputStream is = Resources.getResourceAsStream("mybatis-config.xml");//<2> 创建sessionFactory对象SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);//<3> 获取sqlSession对象信息SqlSession session = sessionFactory.openSession();//<4> 构建映射器的代理对象SysUserMapper mapper = session.getMapper(SysUserMapper.class);//<5>调用相关方法信息SysUserPO sysUserPO = mapper.selectById(1L);

加载配置文件

我们进入<1>处的方法的:
在这里插入图片描述
我们发现一个陌生的对象classLoaderWrapper,看着像一个类加载器,我们进入这个类中查看:
在这里插入图片描述
发现这个对象包含两个类加载器,那么classLoaderWrapper也是关于进行类加载的对象。
我们进入getResourceAsStream方法中查看:
在这里插入图片描述
注意这里传入了一个空的类加载器对象,进入最底层:
在这里插入图片描述我们发现这里传入了一个类加载器的数组,并且遍历了这个类加载器数组,然后尝试让类加载加载这个资源,加载成功后就立即返回。
但是这个类加载器数组是什么呢?我们返回上一层方法查看:
在这里插入图片描述
进入这个返回类加载器数组的方法:

    ClassLoader[] getClassLoaders(ClassLoader classLoader) {return new ClassLoader[]{//null,传入的时候为nullclassLoader,//classLoaderWrapper对象的类加载器变量this.defaultClassLoader, //关于当前线程的类加载器Thread.currentThread().getContextClassLoader(), //当前类的类加载器this.getClass().getClassLoader(), //classLoaderWrapper对象的另一个类加载器变量this.systemClassLoader};}

加载配置文件的流程

通过以上的代码追踪,<1>的步骤如下:通过classLoaderWrapper对象的类加载器变量对mybatis的配置文件进行加载,返回了一个输入流。

创建sqlsessionFactory对象

步骤<2>中我们发现创建啦一个SqlSessionFactoryBuilder对象并且通过build方法返回了sqlsessionFactory对象,我们进入方法查看:
在这里插入图片描述
该方法内首先通过步骤<1>获取的输入流创建了一个XmlConfigBuilder对象,然后调用了其parse方法,我们先查看parse方法:
在这里插入图片描述
这个方法首先是对mybatis配置文件标签进行了解析,并且返回了configuration对象,那么这个解析配置的方法应该是对configration对象的属性进行了填充,那么这个configuration对象是什么呢?我们进入这个类查看:
在这里插入图片描述
可以看到Configuration类中含有许多变量,包括我们很熟悉的缓存、请求映射和返回结果映射,我们其实就可以想到整个解析配置的方法中应该是对配置文件中的每个标签进行了解析然后填充到Configuration对象中,我们查看这个解析方法:

解析Mapper

在这里插入图片描述
进入这个方法中,我们可以发现确实如此,对每个标签进行了解析,我们查看一个很关键的方法mapperElement:
在这里插入图片描述

我们发现生成了一个迭代器,应该是对mappers的多个子标签mapper进行了遍历,然后获取mapper标签的多个属性,可以看到mapper存在三个属性,分别是resource、url、class,由下方的非空判断可知这三者是互斥的,进行判断后,由通过属性对每一个mapper进行加载获取输入流,然后又创建了XmlMapperBuilder,调用其parse方法对每一个mapper进行解析,进入方法:
在这里插入图片描述
我们发现,第一个方法对mapper标签进行了解析,我们进入第一个方法:
在这里插入图片描述
可以看到,这个方法对mapper标签下的每一条sql进行了解析,包括缓存、请求映射、响应结果映射、查询类型等,我们注意上方我框起来的方法:获取mapper的命名空间,并且存储在了一个对象中。
我们接着查看第二个方法:
在这里插入图片描述
还记得上面讲的吗,我们获取对mapper进行解析时存储的mapper的命名空间,然后通过命名空间进行加载获取了mapper的类型,然后这个addMapper方法看起来好像是对configuration对象的属性进行了填充,并且传入了mapper的类型,我们点进去查看:
在这里插入图片描述
这里又出现了MapperRegistry对象,是Configuration对象的变量,继续查看:
在这里插入图片描述在这里插入图片描述
这里创建了一个MapperProxyFactory对象,似乎是创建mapper代理工厂,并且把mapper和代理工厂放入一个map集合中。
我们再回到sqlsessionFactory的创建:
在这里插入图片描述
发现我们之前通过XmlConfigBuider解析的配置文件的标签以及通过XmlMapperBuilder解析的每一个mapper的标签得到的Configuration对象,通过这个Configuration对象创建了DefalutSqlsessionFactory。

创建sqlsessionFactory流程

首先创建了XmlConfigBuilder对象,解析mybatis配置文件,来填充Configuration,在解析<mappers标签过程中,创建了XmlMapperBuilder对象解析每一个mapper中的标签,并且利用了Configuration对象的mapperRegistry的map变量,存储了键为mapper类型,值为mapper代理工厂。

获取sqlsession

进入方法最底层:

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {Transaction tx = null;DefaultSqlSession var8;try {// 获取sqlsessionFactory的configuration变量的环境Environment environment = this.configuration.getEnvironment();// 通过环境获取事务工厂TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);// 创建新的事务tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);// 通过configuration创建ExecutorExecutor executor = this.configuration.newExecutor(tx, execType);// 通过Configuration和Executor创建sqlSessionvar8 = new DefaultSqlSession(this.configuration, executor, autoCommit);} catch (Exception var12) {this.closeTransaction(tx);throw ExceptionFactory.wrapException("Error opening session.  Cause: " + var12, var12);} finally {ErrorContext.instance().reset();}return var8;}

创建mapper代理

第<4>步返回了一个mapper对象,但不是实际的mapper,而是mapper的代理对象,我们进入方法最底层:
在这里插入图片描述
我们发现会从关于mapper代理工厂的map集合中,通过mapper类型获取代理工厂,并且通过代理工厂创建代理对象,点进去查看:
在这里插入图片描述
mapper代理对象的创建是基于JDK动态代理实现的,通过Proxy的newProxyInstance方法创建:
在这里插入图片描述
而创建代理的方法第三个参数是InvocationHandler,那么mapperProxy一定实现了InvocationHandler这个类,并且当我们调用代理对象的方法时,代理类的方法会中转到InvocationHandler对象的invoke方法,然后就可以在这个方法中对原方法做出一些增强,具体可参考:代理模式:静态代理和动态代理(JDK动态代理原理)

执行mapper方法

我们来查看使用代理模式做了哪些增强:
在这里插入图片描述
在这个方法中,首先判断这个类是不是接口,由于JDK动态代理生成的代理类需要继承Proxy类,又需要实现或继承被代理类来获取方法信息,但是java是多实现单继承,因此这个类必须是接口,然后判断是不是默认方法。
查看第一个方法:
在这里插入图片描述
发现是从缓存中获取一个MapperMethod对象,如果不存在进行创建,创建时可以发现闯入了mapper接口、调用的方法以及sqlsession的configuration对象,并且执行方法时也调用了其execute方法,我们看一下MapperMethod到底是什么:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

其存在两个对象,分别是sql命令和方法签名,sql命令包括sql的类型和statement的id,方法签名包括方法的返回类型以及一些信息。
查看execute方法
在这里插入图片描述
首先会根据sql的类型,来选择执行方法,然后将参数装换为sql可以识别的参数,然后再次交给sqlsession来执行方法,我们随机进入一个执行方法查看:

在这里插入图片描述
可以发现会通过Configuration创建MappedStatement,然后由Executor来执行相关方法

总结:MyBatis执行一条sql语句的流程

加载配置文件:通过类加载器ClassLoaderWrapper以及一些其他的类加载器加载mybatis配置文件获得输入流。
SqlsessionFactory的创建:通过XmlConfigBuilder通过输入流解析配置文件的标签,来填充Configuration属性,在解析的mappers标签的过程中,遍历每一个mapper标签,通过mapper标签的属性解析相应的mapper,并通过XmlMapperBuilder对相应的mapper类的标签进行解析,在此期间,通过mapper的命名空间获取mapper类,并且创建mapper代理工厂,以mapper类为键,mapper代理工厂为值放入mapperRegistry的map集合中。
获取sqlsession:通过SqlsessionFactory的Configuration对象获取环境变量,通过环境变量获取事务工厂并且创建事务,然后通过事务和环境创建Executor对象,最后通过创建的Executor对象和事务来创建DefaultSqlsession并返回
获取代理对象:根据mapper类从关于mapper代理工厂的键值对中取出mapper代理工厂并且创建代理对象返回
执行相关方法:由于创建代理对象时传入了MapperProxy对象,其实现了InvocationHandler接口,因此调用代理相关方式时会进入MapperProxy的invoke方法,在该方法内首先会从缓存中获取MapperMethod对象,然后调用其Execute方法,根据sql的类型然后由Executor执行。

相关文章:

MyBatis执行一条sql语句的流程(源码解析)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 MyBatis执行一条sql语句的流程&#xff08;源码解析&#xff09; MyBatis执行sql语句的流程加载配置文件加载配置文件的流程 创建sqlsessionFactory对象解析Mapper创建sqlses…...

【电机控制】低通滤波器及系数配置

【电机控制】低通滤波器及系数配置 文章目录 [TOC](文章目录) 前言一、低通滤波器原理二、理论计算三、代码四、参考资料总结 前言 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、低通滤波器原理 二、理论计算 三、代码 //低通滤波 pv->Ealpha…...

ArcgisServer过了元旦忽然用不了了?许可过期

昨天过完元旦之后上班发现好多ArcgisServer的站点运行出错了&#xff0c;点击日志发现&#xff0c;说是许可过去&#xff0c;也就是当时安装ArcgisServer时读取的ecp文件过期了&#xff0c;需要重新读取。 解决方法 1.临时方法&#xff0c;修改系统时间&#xff0c;早于2024年…...

如何在不丢失数据的情况下从 IOS 14 回滚到 IOS 13

您是否后悔在 iPhone、iPad 或 iPod touch 上安装 iOS 14&#xff1f;如果你这样做&#xff0c;你并不孤单。许多升级到 iOS 14 beta 的 iPhone、iPad 和 iPod touch 用户不再适应它。 如果您在正式发布日期之前升级到 iOS 14 以享受其功能&#xff0c;但您不再适应 iOS 14&am…...

【算法刷题】链表

文章目录 环形链表判断是否有环找出环的入口位置 双指针反转链表&#xff08;Reverse a Linked List&#xff09;移除链表中的指定元素&#xff08;Remove Linked List Elements&#xff09; 环形链表 判断是否有环 环形链表是指链表中的某些节点的 next 指针指向了链表中的某…...

计算机网络 —— 网络编程实操(1)(UDP)

计算机网络 —— 网络编程实操&#xff08;UDP&#xff09; 套接字端口套接字的定义为什么需要套接字&#xff1f; 套接字的分类1. 按照通信协议分类2. 按照地址族&#xff08;Address Family&#xff09;分类3. 按照通信模式分类 socket APIsockaddr结构 使用接口套接字初始化…...

selenium 确保页面完全加载

在使用Python和Selenium进行Web自动化时&#xff0c;确保页面完全加载是非常重要的。为了实现这一点&#xff0c;Selenium提供了两种主要类型的等待&#xff1a;显式等待&#xff08;Explicit Waits&#xff09;和隐式等待&#xff08;Implicit Waits&#xff09;。此外&#x…...

[极客大挑战 2019]HardSQL 1

看了大佬的wp&#xff0c;没用字典爆破&#xff0c;手动试出来的&#xff0c;屏蔽了常用的关键字&#xff0c;例如&#xff1a;order select union and 最搞的是&#xff0c;空格也有&#xff0c;这个空格后面让我看了好久&#xff0c;该在哪里加括号。 先传入1’ 1试试&#…...

vip与haproxy构建nginx高可用集群传递客户端真实ip

问题 系统使用了vip与haproxy实现高可用以及对nginx进行负载均衡&#xff0c;但是发现在上游的应用服务无法拿到客户端的请求ip地址&#xff0c;拿到的是主haproxy机器的ip&#xff0c;以下是nginx与haproxy的缩减配置&#xff1a; location ~* ^/(xx|xx) {proxy_pass http:/…...

Easticsearch介绍|实战?

Elasticsearch 是一个分布式的、RESTful 风格的搜索和数据分析引擎&#xff0c;适用于各种用例&#xff0c;如日志分析、全文搜索、实时应用监控等。它设计用来处理大量数据&#xff0c;并且可以快速地提供相关的搜索结果。以下是一些 Elasticsearch 的实战应用场景以及如何在这…...

Python图形界面(GUI)Tkinter笔记(二十一):Messagebox信息提示功能控件

messagebox 就像是 tkinter 库里的一个好帮手,它能帮你弹出各种各样的消息框给用户看。这些消息框可以告诉用户很多东西,比如提示、警告或者错误信息之类的。在 tkinter 库里,messagebox 这个模块有很多不同的函数,每个函数都能弹出一种特定的消息框。用这些函数,开发者可…...

vue3+ts+element-plus 表单el-form取消回车默认提交

问题描述&#xff1a;在表单el-form中的el-input中按回车后&#xff0c;页面会刷新&#xff0c;url也会改变&#xff0c; 回车前&#xff1a; 回车后&#xff1a; 相关代码&#xff1a; 解决方法1&#xff1a;在 el-form 上阻止默认的 submit 事件&#xff0c;增加 submit.pre…...

Web Services 简介

Web Services 简介 1. 引言 Web Services 是一种基于网络的软件服务,它允许不同的应用程序在互联网上相互通信和交互。这种技术是基于开放的互联网标准,如HTTP、XML、SOAP和WSDL,使得不同平台和编程语言的应用程序能够轻松地实现互操作性。Web Services 的出现,极大地推动…...

Vue3苦逼的学习之路

从一名测试转战到全栈是否可以自学做到&#xff0c;很多朋友肯定会说不可能&#xff0c;或就算转了也是个一般水平&#xff0c;我很认同&#xff0c;毕竟没有经过各种项目的摧残&#xff0c;但是还是得踏足一下这个领域。所以今天和大家分享vue3中的相关内容&#xff0c;大佬勿…...

AcWing练习题:两点间的距离

给定两个点 P1 和 P2&#xff0c;其中 P1P1 的坐标为 (x1,y1)&#xff0c;P2 的坐标为 (x2,y2)&#xff0c;请你计算两点间的距离是多少。 distance√(x2−x1)^2(y2−y1)^2 输入格式 输入共两行&#xff0c;每行包含两个双精度浮点数 xi,yi&#xff0c;表示其中一个点的坐标…...

文献分享:RoarGraph——跨模态的最邻近查询

文章目录 1. \textbf{1. } 1. 导论 1.1. \textbf{1.1. } 1.1. 研究背景 1.2. \textbf{1.2. } 1.2. 本文的研究 1.3. \textbf{1.3. } 1.3. 有关工作 2. \textbf{2. } 2. 对 OOD \textbf{OOD} OOD负载的分析与验证 2.1. \textbf{2.1. } 2.1. 初步的背景及其验证 2.1.1. \textbf{2…...

故事可视化AI

i68,爱六八,链接你我他 StoryWeaver故事可视化 通过知识增强的角色定制技术&#xff0c;实现高质量的故事可视化论文链接:https://arxiv.org/pdf/2412.07375项目仓库:https://github.com/Aria-Zhangjl/StoryWeaver由厦门大学多媒体可信感知与高效计算教育部重点实验室和网易伏…...

【机器学习篇】从新手探寻到算法初窥:数据智慧的开启之门

文章目录 【机器学习篇】从新手探寻到算法初窥&#xff1a;数据智慧的开启之门前言一、什么是机器学习&#xff1f;二、机器学习的基本类型1. 监督学习&#xff08;Supervised Learning&#xff09;2. 无监督学习&#xff08;Unsupervised Learning&#xff09;3. 半监督学习&a…...

ffmpeg八大开发库

‌FFmpeg八大库‌是指FFmpeg项目中最重要的八个库&#xff0c;它们各自承担不同的功能&#xff0c;共同构成了FFmpeg的强大功能。以下是这八大库的详细介绍&#xff1a; ‌libavcodec‌&#xff1a;负责音频和视频的编解码。它支持多种编解码器&#xff0c;如H.264、AAC、MP3、…...

【ArcGISPro/GeoScenePro】解决常见的空间参考和投影问题

修复空间参考缺失的图像 数据 https://arcgis.com/sharing/rest/content/items/535efce0e3a04c8790ed7cc7ea96d02d/data 查看属性坐标 查看属性范围 范围值并不是零或接近于零。 这意味着栅格具有范围,因此其已正确进行...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...