目录
Demo:动态SQL
<select id="countByMap" resultType="int">
select count(id) from person
<where>
<if test="id != null">
AND id = #{id}
</if>
<if test="name != null">
AND name = ${name}
</if>
<if test="description != null">
AND description = #{description}
</if>
</where>
</select>
传参Map:id=1,name=ss
1. Xml中Sql节点解析——存储到SqlSource对象
-
在【MyBatis详解】——从Xml配置解析到SQL执行过程
的配置解析——SQL解析阶段,
XMLScriptBuilder调用了parseScriptNode方法: -
此SqlSource被解析为动态sql,所以为DynamicSqlSource类型;其rootSqlNode祖节点为MixedSqlNode类型,即一个3个子节点的数组:
第1个子节点为静态sql类型:
同样的第3个子节点为静态sql类型:
关键看第2个子节点,为WhereSqlNode类型:
在Where节点中,又包括了两个if标签的内容,都被保存为StaticTextSqlNode静态sql类型。- 注意此时的#和$符号都还没用被替换掉
- if标签为true或者false的节点都被保存了下来
2. Sql执行——通过调用SqlSource.getBoundSql得到动态处理过的Sql
- 在【MyBatis详解】——从Xml配置解析到SQL执行过程
的Executor执行SQL阶段,在StatementHandler被创建的过程中,有一个getBoundSql的步骤:
然后将调用上一步得到的SqlSource的getBoundSql方法:
1. SqlNode.apply处理动态内容
- 解析if等动态标签,只有test条件为true时,才append对应sql
- 把$符号替换为参数,直接拼接sql
- SqlNode
节点解析时的工具类,简单理解就是xml中的每个标签,如update,trim,if标签
其实现类包括
实现动态Sql的关键就是 各个SqlNode的 apply方法;
以IfSqlNode为例,如果满足条件,则append标签中的内容,并返回true:
而StaticTextSqlNode类型静态sql,则直接append
2. SqlSourceParser.parse替换#符号为?
最终得到的是JDBC格式的SQL,实现动态Sql的关键是各个SqlNode的 apply方法。