在 XMLScriptBuilder 的parseScriptNode()方法中解析每个sql语句。
package org.apache.ibatis.scripting.xmltags;public class XMLScriptBuilder extends BaseBuilder {public SqlSource parseScriptNode() {MixedSqlNode rootSqlNode = parseDynamicTags(context);SqlSource sqlSource;if (isDynamic) {sqlSource = new DynamicSqlSource(configuration, rootSqlNode);} else {sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);}return sqlSource;}protected MixedSqlNode parseDynamicTags(XNode node) {List<SqlNode> contents = new ArrayList<>();NodeList children = node.getNode().getChildNodes();for (int i = 0; i < children.getLength(); i++) {XNode child = node.newXNode(children.item(i));if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) {String data = child.getStringBody("");TextSqlNode textSqlNode = new TextSqlNode(data);if (textSqlNode.isDynamic()) {contents.add(textSqlNode);isDynamic = true;} else {contents.add(new StaticTextSqlNode(data));}} else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628String nodeName = child.getNode().getNodeName();NodeHandler handler = nodeHandlerMap.get(nodeName);if (handler == null) {throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement.");}duanhandler.handleNode(child, contents);isDynamic = true;}}return new MixedSqlNode(contents);}}
上面parseDynamicTags方法中判断sql语句中是否有“${}”,如果有一个地方含有动态语句,则这个sql就是动态sql,即为DynamicSqlSource类型,否则为RawSqlSource类型。
解析静态sql
package org.apache.ibatis.scripting.defaults;
public class RawSqlSource implements SqlSource {
private final SqlSource sqlSource;
public RawSqlSource(Configuration configuration, SqlNode rootSqlNode, Class<?> parameterType) {
this(configuration, getSql(configuration, rootSqlNode), parameterType);
}
public RawSqlSource(Configuration configuration, String sql, Class<?> parameterType) {
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class<?> clazz = parameterType == null ? Object.class : parameterType;
sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap<>());
}
private static String getSql(Configuration configuration, SqlNode rootSqlNode) {
DynamicContext context = new DynamicContext(configuration, null);
rootSqlNode.apply(context);
return context.getSql();
}
@Override
public BoundSql getBoundSql(Object parameterObject) {
return sqlSource.getBoundSql(parameterObject);
}
}
由上面代码可以看出,对于静态sql,其在构建RawSqlSource对象时,就会解析sql。例如将”#{}”替换为”?”。
在解析时,对于标签例如:WhereSqlNode、IfSqlNode 以及含有${}的TextSqlNode等都是动态DynamicSqlSource,文本内容保持不变,例如IfSqlNode的sqlSource为”name = #{name,jdbcType=VARCHAR}”,而TextSqlNode中包含${}时sqlSource为”id = ${id}”,其他静态TextSqlNode则会将”#{}”替换为”?”。
