java程序
xml文件
直接进入到解析select语句的地方
进入
解析xml
进入buildStatementFromContext,依然是交给XMLStatementBuilder解析
核心部分创建SqlSource
交给XMLLanguageDriver后再转到XMLScriptBuilder
先读取xml配置, 读到一个MiedSqlNode中,主要是将xml节点的层次结构。
解析语句第一部分
先解析<#text> SELECT * FROM POST P WHERE id in #text>
比较简单,直接封装成StaticTextSqlNode。
解析Foreach
,
进入ForeacHandler,
进入内部标签解析,开始解析foreach内部,第一个元素是一个文本,仅仅含有一个\n换行,所以最后封装成一个StaticTextSqlNode
第二次循环,解析,
根据标签名,选择ifHandler处理
在IfHandler中,与ForeachHanlder相似,有3步
解析If
内部就是一个逗号,所以处理 就直接封装成一个StaticTextSqlNode
解析 #{item}
比较简单,也是一个StaticTextSqlNode
最后还有一个\n换行(后面继续调试,发现后有个循环)
问题不大,就是一个StaticSqlTextNode
解析完毕 查看MiexedSqlNode节点
是一个树形结构 未包含最后一个换行
if节点展开
解析完毕 封装DynamicSqlSource
明显会封装成DynamicSqlSource
所有内部含有子标签,或者有${}未处理完毕的都是动态sql
封装成MappedStatement
通过一个简单的构建者模式,生成MappedStatement,保存到configuration,这部分代码不截图了,意义不大。
执行sql
直接进入到下图
封装查询参数比较简单
正式开始
先交给CacheExecutor执行,先拿取到BoundSql
通过MappedStatement去拿,MappedStatement转sqlSource处理,我们这里的sqlSource是DynamicSqlSource。
进入到DynamicSqlSource
可以看到第一二行代码,进行动态处理。
与StaticSqlSource不同,StaticSqlSource只需要封装一个BoundSql返回即可,因为解析xml阶段就处理完毕了。DynamicSqlSource还需要在执行过程中进行处理。
实例化一个DynamicContext对象
核心第二步开始 对sqlNode树进行操作
rootSqlNode.apply(context);
MiexedSqlNode转交内部结构自己去处理
处理第一个文本节点
SELECT * FROM POST P WHERE id in
这个StaticSqlNode先行处理,比较简单,直接拼接文本
处理foreach节点
对foreach进行处理
在保存对应参数处理中,将参数存储为自身定义的格式,后续进行相应的替换
内部节点继续进行处理
同样通过MixedSqlNode交给具体SqlNode进行处理
第一个换行节点跳过
解析if
因为是第一个节点 test内容是 index!=0所以会返回false,
否则会进入判断内部,继续对内部的节点进行处理。
后续第二次第三次,会进入判断里面,处理的会将 内部的StaticSqlNode节点进行处理。
因为就是一个逗号文本, 所以返回文本逗号。
这里的处理就是逗号分隔,第一个不要逗号。
解析#{item}
交给Foreach节点下的FilteredDynamicContext处理
通过GenerictokenParser去解析,token解析器将对应的标签专成 前面存储的类型。
再拼接到语句后面。
主要先通过FilteredDynamicContext对元素进行封装,封装格式
__frch_{item}_{index}
PrefixedContext
DynamicContext生成完毕
SqlSourceBuilder解析sql生成StaticSqlSource
和静态解析一样,对#{}占位符转?处理
直接到SimpleExecutor的doQuery方法
先生成statementHandler
前面获取到了再和对应的静态执行一样。
完毕。
总结
后续对静态sql再进行深入研究。
xml解析理解更加深刻了。对于树结构处理,其实就用到了先序遍历。
对他内部的抽象理解更近一步。