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,一经查实,立即删除!

相关文章

KMP算法----java实现

字符串的模式匹配本文先实现最基本的回溯实现的已经KMP算法,BM算法后面博文继续实现。ps:本篇博文强烈参考了July大神的作品,地址http://blog.csdn.net/v_july_v/article/details/6545192.再次感激大神~~ 1.最基本的回溯实现字符串模式匹配 package com.…

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

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

PHP面向对象2之变量、方法

1 <?php2 /**3 * PHP面向对象基础 调用变量4 */5 class Computer{6 //字段成员的声明格式&#xff1a;修饰符 变量名[xxx]7 public $_name;//public 表示类外可以访问&#xff0c;为公有变量8 public $_model;9 } 10 //创建一个对象…

在 VC6 中使用 GdiPlus-安装

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

算法训练|实现 Trie (前缀树)

208. 实现 Trie (前缀树) - 力扣&#xff08;LeetCode&#xff09; 总结&#xff1a; Trie&#xff0c;又称前缀树或字典树&#xff0c;是一棵有根树&#xff0c;其每个节点包含以下字段&#xff1a; 指向子节点的指针数组 children。对于本题而言&#xff0c;数组长度为 26…

ASP.NET MVC 的多国语系支持

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

airtest web 录制滑块_Airtest之web自动化(一)

Airtest之web自动化(一)[此文档有许多涉及到gif动图的地方&#xff0c;请全屏观看]了解Airtest&#xff1a;简介&#xff1a;Airtest是由网易团队开发的一款自动化框架&#xff0c;前期运用与游戏测试(通过截图识别)&#xff0c;后来又被运用到安卓测试以及web测试。这款自动化…

error C2065: 'ULONG_PTR' : undeclared identifier

处理方法: 把#define ULONG_PTR ULONG 加到 stdafx文件 靠前面的位置 原因&#xff1a; Visual C 6.0 开发环境, gdi 的头文件和库文件并没有被包含在环境中, 需要您手工安装 VC6 中没有 ULONG_PTR 类型

重构价格日历

重构价格日历转载于:https://www.cnblogs.com/usual2013blog/p/3728655.html

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

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

RegOpenKeyEx 返回值 2

RegOpenKeyEx 返回值 2 x64 系统&#xff1a; 32bit 应用程序调用RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft", 0, KEY_WOW64_64KEY | KEY_READ, &hKey ); 注意 KEY_WOW64_64KEY 权限值必须使用否则将查找不到指定的路径。

mysql client 未开启_Django+mysqlclient未关闭数据库连接

我使用2个mysql数据库连接。在django中的每个页面请求之后&#xff0c;连接计数(如SHOW STATUS LIKE Conn%所示)每次增加2。在Python 3.4.0django 1.8.2mysqlclient 1.3.6版(Windows和Linux似乎都有这个问题)最初我直接通过MySQLdb访问第二个数据库&#xff0c;但现在我改为使用…

OpenGL中各种坐标系的理解

OPENGL坐标系可分为&#xff1a;世界坐标系和当前绘图坐标系。 世界坐标系&#xff1a;在OpenGL中&#xff0c;世界坐标系是以屏幕中心为原点(0, 0, 0)&#xff0c;且是始终不变的。你面对 屏幕&#xff0c;你的右边是x正轴&#xff0c;上面是y正轴&#xff0c;屏幕指向你的为z…

默认手机照相功能

下面是主要代码: - (void) addPicEvent { //先设定sourceType为相机&#xff0c;然后判断相机是否可用&#xff08;ipod&#xff09;没相机&#xff0c;不可用将sourceType设定为相片库 UIImagePickerControllerSourceType sourceType UIImagePickerControllerSourceT…

qmake生成vs2013工程文件

qmake -spec win32-msvc2013 -r -tp vc xxx.pro

iOS面试题

今天上午&#xff0c;下午分别面试了两家公司。上午是一家互联网公司&#xff0c;气氛还比较好&#xff0c;是我比较喜欢的。技术这块是直接机试&#xff0c;主要是给了些BUG让我修复&#xff0c;整个过程还算顺利。下午去了一家大型的证券公司。整理技术问题如下&#xff1a; …

Prepar3d.cfg

如果设置为0&#xff0c;打开p3d直接进入默认场景 [USERINTERFACE] SHOW_SCENARIO_WINDOW1

mysql严格模式 报错_mysql严格模式

mysql严格模式严格模式例子1234567DB::table(table_name)->where(status, 1)->select(DB::raw(sum(score) as num,user_id,channel))->groupBy(user_id)->orderBy(num, desc)->limit(10)->get();会报错&#xff1a;Syntax error or access violation: 1055 E…

Android Service 的一些笔记

绑定服务&#xff1a; 用于间接调用服务里面的方法。如果调用者Activity被销毁了&#xff0c;服务也跟着销毁了&#xff0c;服务也会跟着销毁。 开启服务&#xff1a; 不可以调用服务里面的方法。如果调用者的Activity退出了&#xff0c;服务还会长期在后台运行 生命周期 ①单独…

python traceback 丢失_基于python traceback实现异常的获取与处理

这篇文章主要介绍了基于python traceback实现异常的获取与处理,文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下1、traceback.print_exc()2、traceback.format_exc()3、traceback.print_exception()简单说下这三个…