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执行。

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

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

相关文章

【C++】探索C++11中的范围for循环与auto关键字

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;1. 范围for循环的基础用法1.1 什么是范围for循环&#xff1f;1.2 示例代码代码解析 1.3 范围for的特点传统for循环与范围for循环对比 1.4 使用引用修改元素 &#x1f4af;2…

mac下载Homebrew安装nvm

通过Homebrew安装 - 国内下载地址 /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"安装nvm brew install nvm 配置nvm环境变量 export NVM_DIR“$HOME/.nvm” [ -s “/usr/local/opt/nvm/nvm.sh” ] && . “/usr/…

解決當前IP地址僅適用於本地網路

想要解決“當前IP地址僅適用於本地網路”其實並不困難。本篇文章將介紹其發生的原因以及如何解決。 “僅限本地網路”是什麼意思&#xff1f; 當IP地址為“僅限本地網路”時&#xff0c;意味著設備正在使用私人網路內部IP地址&#xff0c;但無法連接到互聯網。如果將本地IP視…

HANA数据库 XS 503 Service not available

http_url配置正确 在将单个数据库系统转换为多租户数据库容器系统之后&#xff0c;无法通过URL访问新租户数据库的独立XS引擎服务。调用相应的URL会产生这样的错误&#xff1a;503服务不可用 Solution &#xff08;启用租户数据库引擎的嵌套模式&#xff08;HDD不用&#xff…

【大模型实战篇】Mac本地部署RAGFlow的踩坑史

1. 题外话 最近一篇文章还是在11月30日写的&#xff0c;好长时间没有打卡了。最近工作上的事情特别多&#xff0c;主要聚焦在大模型的预训练、微调和RAG两个方面。主要用到的框架是Megatron-DeepSpeed&#xff0c;后续会带来一些分享。今天的文章主要聚焦在RAG。 近期调研了一系…

推荐5款局域网IP扫描工具,支持电脑+Android!

在日常网络管理中&#xff0c;快速扫描局域网中的设备和IP地址是一项基本但非常重要的任务。无论是排查网络问题还是进行设备管理&#xff0c;一款好用的 IP 扫描工具都能让你事半功倍。 如何选择适合自己需求的局域网 IP 扫描工具&#xff1f;有哪些功能强大又易于上手的工具…

python修改ppt中的文字部分及插入图片

批量修改ppt中的某个模块&#xff0c;或者批量制作奖状等场景会用到&#xff1b; import os import pandas as pd from pptx import Presentation from pptx.util import Inchesfilepath/Users/kangyongqing/Documents/kangyq/202303/分析模版/批量制作/file1时段预警_副本.pp…

计算机网络—————考研复试

第一章、计算机网络体系结构 1. OSI参考模型和TCP/IP模型&#xff1a; OSI与TCP/IP的记忆方法&#xff1a;只需把OSI的七层记住&#xff0c;将应用层、表示层、会话层一起记&#xff0c;到TCP/IP变成应用层。物理层和数据链路层换成网络接口层。把网络层换个字变成网际层。 而…

springboot534售楼管理系统(论文+源码)_kaic

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本售楼管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&am…

计算机体系结构期末复习3:GPU架构及控制流问题

目录 一、GPU设计思路 1.简化流水线、增加核数 2.单指令多线程&#xff08;SIMT&#xff09; 3.同时驻留大量线程 4.总思路&#xff1a;多线程单指令多线程 二、GPU的控制流问题 1.什么是控制流问题 2.怎么应对分支分歧 一、GPU设计思路 1.简化流水线、增加核数 2.单指…

[实用指南]如何将视频从iPhone传输到iPad

概括 将视频从 iPhone 传输到 iPad 时遇到问题&#xff1f;您可能知道一种方法&#xff0c;但不知道如何操作。此外&#xff0c;您要传输的视频越大&#xff0c;完成任务就越困难。那么如何将视频从 iPhone 传输到 iPad&#xff0c;特别是当您需要发送大视频文件时&#xff1f…

httpslocalhostindex 配置的nginx,一刷新就报404了

当你的Nginx配置导致页面刷新时报404错误时&#xff0c;通常是由于以下几个原因造成的&#xff1a; 静态文件路径配置错误&#xff1a;Nginx没有正确地指向静态文件的目录。前端路由问题&#xff1a;如果是SPA&#xff08;单页应用&#xff09;&#xff0c;刷新页面时Nginx没有…

药片(药丸)和胶囊识别数据集,使用yolo,pasical voc xml, coco json格式标注,可识别药片和胶囊两种标签,2445张原始图片

药片(药丸)和胶囊识别数据集&#xff0c;使用yolo&#xff0c;pasical voc xml, coco json格式标注&#xff0c;可识别药片和胶囊两种标签&#xff0c;2445张原始图片 数据集分割 训练组80&#xff05; 1967图片 有效集13% 317图片 测试集7% 161图片 预处…

解决winform中comboBox下拉不够长的问题

默认情况下的combobox 可以看到comboBox不够长 导致信息显示不完成 解决方法 修改属性&#xff1a;DropDownWidth为308 修改前修改后

HTML——43.创建表格

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>表格</title></head><body><!--table标签用来定义表格&#xff0c;border属性表示边框--><!--tr标签表示表格中的一行--><!--th标签表示表…

在 Ubuntu 上安装和使用 `opus-tools` 的详细教程

目录 1. **安装 opus-tools**2. **opus-tools 常用命令** 2.1 **opusenc - 编码音频文件为 Opus 格式**示例 1&#xff1a;将 WAV 文件编码为 Opus 格式示例 2&#xff1a;设置编码比特率示例 3&#xff1a;使用变比特率&#xff08;VBR&#xff09;示例 4&#xff1a;设置声道…

[硬件] DELL BIOS 相关注意事项

前言 前段时间重装系统. DELL BIOS属实资料少, 又难用. 这里给出相关的注意事项, 并且配上图片. BIOS相关注意事项 进入BIOS ESC/F2/ F12. 都可以进入BIOS, 当进U盘的入Win PE系统时, 使用F12 效果更佳. 关闭安全模式 切换到Boot Configuration选项,将Secure Boot选项off选…

ip归属地怎么判定?如何查看自己ip属地

在当今数字化时代&#xff0c;IP地址作为互联网通信的基础&#xff0c;扮演着至关重要的角色。而IP归属地的判定与查看&#xff0c;不仅关乎网络安全、隐私保护&#xff0c;还直接影响到社交平台的信任机制与信息传播的真实性。本文将深入探讨IP归属地的判定原理以及如何查看自…

大数据与机器学习(它们有何关系?)

想了解大数据和机器学习吗&#xff1f;我们将为你解释它们是什么、彼此之间有何关联&#xff0c;以及它们为何在数据密集型应用中如此重要。 大数据和机器学习是如何相互关联的&#xff1f; 大数据指的是传统存储方法无法处理的海量数据。机器学习则是计算机系统从观察结果和…

前端安全措施:接口签名、RSA加密、反调试、反反调试、CAPTCHA验证

文章目录 引言I 设置防爬虫功能使用robots.txt文件通过配置HTTP头部中的X-Robots-TagII 禁止打开开发者工具反复清空控制台无限debugger反调试检查是否按下了F12或其他调试快捷键禁用右键监听调试快捷键例子III 屏蔽粘贴/复制/剪切/选中IV 知识扩展: javascript内置命令调试分…