框架大集合|【MyBatis详解】——动态SQL解析与执行原理


目录

  • Demo:动态SQL
  • 1. Xml中Sql节点解析——存储到SqlSource对象
  • 2. Sql执行——通过调用SqlSource.getBoundSql得到动态处理过的Sql
    • 1. SqlNode.apply处理动态内容
    • 2. SqlSourceParser.parse替换#符号为?

Demo:动态SQL
="countByMap" resultType="int"> select count(id) from person AND id = #{id} AND name = ${name} AND description = #{description}

【框架大集合|【MyBatis详解】——动态SQL解析与执行原理】传参Map:id=1,name=ss
1. Xml中Sql节点解析——存储到SqlSource对象
  • 在【MyBatis详解】——从Xml配置解析到SQL执行过程
    的配置解析——SQL解析阶段,
    XMLScriptBuilder调用了parseScriptNode方法:
  • 此SqlSource被解析为动态sql,所以为DynamicSqlSource类型;其rootSqlNode祖节点为MixedSqlNode类型,即一个3个子节点的数组:
    框架大集合|【MyBatis详解】——动态SQL解析与执行原理
    文章图片

    第1个子节点为静态sql类型:
    框架大集合|【MyBatis详解】——动态SQL解析与执行原理
    文章图片

    同样的第3个子节点为静态sql类型:
    框架大集合|【MyBatis详解】——动态SQL解析与执行原理
    文章图片

    关键看第2个子节点,为WhereSqlNode类型:
    框架大集合|【MyBatis详解】——动态SQL解析与执行原理
    文章图片

    在Where节点中,又包括了两个if标签的内容,都被保存为StaticTextSqlNode静态sql类型。
    • 注意此时的#和$符号都还没用被替换掉
    • if标签为true或者false的节点都被保存了下来
      框架大集合|【MyBatis详解】——动态SQL解析与执行原理
      文章图片
2. Sql执行——通过调用SqlSource.getBoundSql得到动态处理过的Sql
  • 在【MyBatis详解】——从Xml配置解析到SQL执行过程
    的Executor执行SQL阶段,在StatementHandler被创建的过程中,有一个getBoundSql的步骤:
    然后将调用上一步得到的SqlSource的getBoundSql方法:
1. SqlNode.apply处理动态内容
  • 解析if等动态标签,只有test条件为true时,才append对应sql
  • 把$符号替换为参数,直接拼接sql
    框架大集合|【MyBatis详解】——动态SQL解析与执行原理
    文章图片
  • SqlNode
    节点解析时的工具类,简单理解就是xml中的每个标签,如update,trim,if标签
    其实现类包括
    框架大集合|【MyBatis详解】——动态SQL解析与执行原理
    文章图片

    实现动态Sql的关键就是 各个SqlNode的 apply方法;
    以IfSqlNode为例,如果满足条件,则append标签中的内容,并返回true:
    框架大集合|【MyBatis详解】——动态SQL解析与执行原理
    文章图片

    而StaticTextSqlNode类型静态sql,则直接append
    框架大集合|【MyBatis详解】——动态SQL解析与执行原理
    文章图片
2. SqlSourceParser.parse替换#符号为? 框架大集合|【MyBatis详解】——动态SQL解析与执行原理
文章图片

最终得到的是JDBC格式的SQL,实现动态Sql的关键是各个SqlNode的 apply方法。

    推荐阅读