sql字符串拼接_Mybatis的SqlSession执行sql过程

2394f52faf620935166d114ad130d75d.png

上一篇分析了SqlSession执行sql的过程,其中并没有分析sql是从哪里来的,今天就来仔细分析下。

Sql来源

从上一篇的最后一步执行sql那里倒推sql的来源,源码主要过程如下图:

709e0f902ebc93a188e451b7f64df69e.png

可以看到最后是通过BoundSql直接获取的sql,然后往前倒推最后发现是通过MappedStatement的getBoundSql方法返回的。MappedStatement在之前分析mapper的时候知道一个执行sql对应一个MappedStatement对象,它封装有mybatis中需要执行一条sql的所有信息,所以从这里获取也是理所应当的。

MappedStatement的getBoundSql方法

那么就来看下MappedStatement的getBoundSql方法吧,源码如下图:

4471ed803f35340f8e91566e39e23ab0.png

首先是右边MappedStatement的getBoundSql方法,这次改了下sql传递了两个参数,但是对程序基本没什么影响。可以看到BoundSql是通过SqlSource创建的,通过debug知道是DynamicSqlSource对象。

左边是DynamicSqlSource的getBoundSql方法,可以先看后面的创建BoundSql对象,是通过SqlSource初始化的,而创建SqlSource对象需要的第一个参数是通过context.getSql()得到的。

而在getBoundSql方法第一步是初始化了context,从上图的debug可以看到目前context的信息,bindings属性已经通过初始化把参数设置进去,而sqlBuilder还是一个空字符串。关键代码就在当前打断点的“rootSqlNode.apply(context);”这行代码。

从上图可以看到rootSqlNode是一个MixedSqlNode对象,MixedSqlNode对象的apply方法是遍历属性contents的所有元素并执行它们的apply方法,可以看到contents只有一个TextSqlNode对象的元素。所以最终来到TextSqlNode对象。

TextSqlNode对象的text属性保存的就是还没有进行处理的sql。

TextSqlNode处理sql

TextSqlNode处理sql的源码如下图:

fadb89f9e455584cb4d2a261085b0479.png

右侧是TextSqlNode的apply方法,参数context就是上一步需要的context,他里面包含有请求参数,从上一张源码图可以知道它的属性sqlBuilder此时还是一个空字符串,而apply就是去拼接sqlBuilder。

apply方法首先创建了一个GenericTokenParser对象,GenericTokenParser对象有三个属性openToken、closeToken、handler。其中openToken、closeToken分别对应字符串”${”、”}”,而handler的属性context对应传递进来的context,injectionFilter属性是TextSqlNode的injectionFilter。apply第二行代码“context.appendSql(parser.parse(text));”可以看出来parser.parse(text)就是生成sql的代码。其中text是TextSqlNode中没有处理的原始sql。

所以sql生成在GenericTokenParser的parse方法,parse方法的关键源码如上图左侧。主要步骤分析如下:

1、从sql找到第一个“${”位置start,获取到元素sql(text)的字符数组src;

2、把src从开始到start处的字符拼接到结果builder上,也就是把“${”的内容拼接到结果上;

3、从start+2的位置开始找“}”的位置end,从src数组里取出“${”、“}”之间的字符组成字符串并根据字符串从hander中取出字符串对应的参数值。并把值拼接到结果builder上。

最后还有一点代码没有截取到“start = text.indexOf(openToken, offset);

} while (start > -1);”也就是第4步。

4、继续找到下一个“${”并拼接。最终组成完整的sql。

实际上GenericTokenParser的parse方法还是比较简单的,就是把传递进来的参数text中openToken、closeToken中间的内容替换成对应的参数。

总结

从之前的分析我们知道一个MappedStatement对应一个sql,那么如何从MappedStatement获取组装好的sql呢,实际上是MappedStatement的属性sqlSource。

而sqlSource实际上是依靠rootSqlNode,在之前我们分析过解析mapper文件是把sql生成了嵌套的各种SqlNode子类。今天就看到他们的使用了。不过今天的算是比较简单的,后面来一个稍微复杂一点的看看sql的解析过程。

Java程序员日常学习笔记,如理解有误欢迎各位交流讨论!

8d9a5a150e07c335330011401b5f175a.png

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

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

相关文章

深入浅出FSUIPC的作用以及使用方法

看此贴前您需要掌握的技能或知识:1. 有FSX或FS2004并正确安装了FSUIPC 2. 具备一定的C语言理解能力,C语言是一切高级语言的基础,单片机主要也用的C语言。 3. 掌握以下几种编程语言之一即可: VC\VB\C#\DELPHI\JAVA\CMFC\.NET版的C或…

在 VC6 中使用 GdiPlus-安装

安装三部曲: Step1:下载 GdiPlus SDK 文件包; 链接地址1:http://www.codeguru.com/code/legacy/gdi/GDIPlus.zip 链接地址2:http://www.codersource.net/samples/mfcgdiplus.zip Step2:安装; &a…

ASP.NET MVC 的多国语系支持

ASP.NET MVC 的多国语系支持 posted on 2014-05-14 11:31 stickout 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/linhui/p/3727364.html

aliyun centos6 安装mysql_阿里云CentOS6.8安装MySQL5.6

1、使用SSH Secure Shell工具连接阿里云服务器2、使用SSH Secure File Transfer工具上传MySQL压缩包3、解压MySQL压缩包到指定目录(需要在先/usr/local下创建mysql目录)进入压缩文件存放位置,进行解打包:tar -xvf MySQL-5.6.22-1.el6.i686.rpm-bundle.ta…

用Javascript获取页面元素的位置

制作网页的过程中,你有时候需要知道某个元素在网页上的确切位置。 下面的教程总结了Javascript在网页定位方面的相关知识。 一、网页的大小和浏览器窗口的大小 首先,要明确两个基本概念。 一张网页的全部面积,就是它的大小。通常情况下&#…

[Qt] 利用QtWebKit完成JavaScript访问C++对象

http://blog.csdn.net/longsir_area/article/details/42965565 一. 介绍 在浏览器扩展或者WebApp的项目经常用的脚本语言JavaScript有很多局限性,比如,javascript语言不能够夸窗口访问js对象,不能直接读写磁盘文件(这个…

mysql三大范式_MySQL学习笔记

1、数据库结构设计1、总-总体流程图2、分-【提取属性】业务分析评价的属性:{用户,课程主标题,内容,综合评分,内容实用,简洁易懂,逻辑分析,发布时间} 问答评论属性:{类型,…

QT webkit 各个类之间关系--QWebView-QWebPag

一、QT webkit简介 1.Qt Qt(发音同 cute)是一个跨平台的C应用程式开发框架,有时又被称为C部件工具箱。Qt被用在KDE桌面环境、Opera、Google Earth、Skype、Adobe Photoshop Album和VirtualBox的开发中。它是挪威Qt Software 的产品&#xff0…

vue 文件转换二进制_在vue中使用axios实现post方式获取二进制流下载文件(实例代码)...

需求点击导出下载表格对应的excel文件在 vue 项目中,使用的 axios ,后台 java 提供的 post 接口 api实现第一步,在 axios 请求中加入参数,表示接收的数据为二进制文件流responseType: "blob"第二步,在拿到数据流之后,把流转为指定文件格式并创建a标签,模拟点击下载,实…

vs生成qt moc文件

1. 右键需要生成moc文件的头文件 2. 将生产的moc加入工程中

javascript好文---深入理解定位父级offsetParent及偏移大小

前面的话 偏移量(offset dimension)是javascript中的一个重要的概念。涉及到偏移量的主要是offsetLeft、offsetTop、offsetHeight、offsetWidth这四个属性。当然,还有一个偏移参照——定位父级offsetParent。本文将详细介绍该部分内容 offsetParent定位父级 在理解…

bash中将字符串split成数组的方法

相信编程时,字符串的处理是很频繁被处理的问题,其中大家肯定不陌生各种语言的string.split(sp)将字符串按照某个字符或子串切分成一个数组。 同样,我们在用shell处理文本信息时也可以方便地实现该功能。 这里主要使用了bash中关于字符串变量的…

理解 e.clientX,e.clientY e.pageX

event.clientX、event.clientY 鼠标相对于浏览器窗口可视区域的X,Y坐标(窗口坐标),可视区域不包括工具栏和滚动条。IE事件和标准事件都定义了这2个属性 event.pageX、event.pageY 类似于event.clientX、event.clientY,…

基于FlashPaper的文档播放器

本文主要讨论、描述了使用Adobe公司的Flex与FlashPaper产品完成对发布到网上的文档资料进行只读控制,也就是说只允许浏览操作、对下载、打印进行控制。FlashPaper FlashPaper是Macromedia的一款用于将操作系统所识别的文档的内容通过虚拟打印机制将内容转换为swf文件…

python经纬度转换xy坐标公式 pyqt_EXCEL公式进行经纬度与XY坐标的相互转换

一、用EXCEL进行高斯投影换算从经纬度B、L换算到高斯平面直角坐标X、Y(高斯投影正算),或从X、Y换算成B、L(高斯投影反算),一般需要专用计算机软件完成。在目前流行的换算软件中不足之处,就是灵活性较差,大都需要一个点一个点地进行…

java桥_JAVA 桥模式

桥梁模式的用意是“将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化”。这句话很短,但是第一次读到这句话的人很可能都会思考良久而不解其意。这句话有三个关键词,也就是抽象化、实现化和脱耦。理解这三个词所代表…

java utf8 byte_byte以及UTF-8的转码规则

https://www.cnblogs.com/hell8088/p/9184336.html多年来闲麻烦,只记录笔记,不曾编写BLOG,本文为原创,如需转载请标明出处废话不说,直奔主题ascii计算机只接受 “高”、“低”电压,所以使用二进制 1 和 …

理解GL_TRIANGLE_STRIP等绘制三角形序列的三种方式

GL_TRIANGLE_STRIP绘制三角形方式很多时候令人疑惑,在这里对其运作机理进行解释。 一般情况下有三种绘制一系列三角形的方式,分别是GL_TRIANGLES、GL_TRIANGLE_STRIP和GL_TRIANGLE_FAN。 如下图所示: GL_TRIANGLES是以每三个顶点绘制一个三…

jpa mysql乐观锁_【快学springboot】8.JPA乐观锁OptimisticLocking

介绍当涉及到企业应用程序时,正确地管理对数据库的并发访问是至关重要的。为此,我们可以使用Java Persistence API提供的乐观锁定机制。它导致在同一时间对同一数据进行多次更新不会相互干扰。为了使用OptimisticLocking,我们需要一个实体(En…

php mysql 库存变负数_php解决秒杀并发入库导致的库存负数

我们知道数据库处理sql是一条条处理的,假设购买商品的流程是这样的:sql1:查询商品库存1 if(库存数量 > 0)2 {3 //生成订单4 //库存-15 >当没有并发时,上面的流程看起来是如此完美,假设同时两个人下单,而库存只有…