mybatis 动态sql 源码解析

mybatis 动态sql

测试例子

java程序

xml文件

调试

直接进入到解析select语句的地方

进入

解析xml

进入buildStatementFromContext,依然是交给XMLStatementBuilder解析

核心部分创建SqlSource

交给XMLLanguageDriver后再转到XMLScriptBuilder

先读取xml配置, 读到一个MiedSqlNode中,主要是将xml节点的层次结构。

解析语句第一部分

先解析<#text> SELECT * FROM POST P WHERE id in </#text>

比较简单,直接封装成StaticTextSqlNode。

解析Foreach

,

 

进入ForeacHandler,

  1. 第一步继续对当前标签内部 进行解析
  2. 将内部属性,解析返回封装成 ForEachSqlNode,可以理解为他自己是个ForEachSqlNode
  3. 将它自己(ForEachSqlNode)加入到他的上级中,这部分代码本身是一个递归操作

进入内部标签解析,开始解析foreach内部,第一个元素是一个文本,仅仅含有一个\n换行,所以最后封装成一个StaticTextSqlNode

第二次循环,解析,

根据标签名,选择ifHandler处理

在IfHandler中,与ForeachHanlder相似,有3步

  1. 解析内部元素
  2. 处理自身需要的属性,并封装为IfSqlNode
  3. 将自身加入到父级SqlNode

解析If

内部就是一个逗号,所以处理 就直接封装成一个StaticTextSqlNode

解析 #{item}

比较简单,也是一个StaticTextSqlNode

最后还有一个\n换行(后面继续调试,发现后有个循环)

问题不大,就是一个StaticSqlTextNode

解析完毕 查看MiexedSqlNode节点

是一个树形结构 未包含最后一个换行

if节点展开

解析完毕 封装DynamicSqlSource

明显会封装成DynamicSqlSource

所有内部含有子标签,或者有${}未处理完毕的都是动态sql

封装成MappedStatement

通过一个简单的构建者模式,生成MappedStatement,保存到configuration,这部分代码不截图了,意义不大。

执行sql

直接进入到下图

  1. 先通过id拿到前面通过xml解析封装成的MappedStatement
  2. 封装查询参数
  3. 交给执行器去执行

封装查询参数比较简单

  1. 集合,数组封装成map,key不一样而已
  2. 对象原样返回

正式开始

先交给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解析理解更加深刻了。对于树结构处理,其实就用到了先序遍历。

对他内部的抽象理解更近一步。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值