mybatis源码解读二动态sql标签解析

每个 select、insert /、update 、delete 对应一个 MappedStatement 对象,每个MappedStatement 包含一个SqlSource,
一个SqlSource含有一个MixedSqlNode,静态sql,${},include在解析mpper文件生成MixedSqlNode时,就已经被替换和解析、
DynamicSqlSource:处理动态sql,
RawSqlSource:处理静态sql,其内部装饰StaticSqlSource。
StaticSqlSource:处理静态sql,无论是静态sql,还是动态sql,最终的处理结果,都是静态sql。
ProviderSqlSource:处理注解Annotation形式的sql。
DynamicSqlSource和StaticSqlSource的最大区别在于:StaticSqlSource的String sql,可以直接获取使用,而DynamicSqlSource的String sql需要逐一根据条件解析并拼接出最终的sql,方能使用。

	<select id="selectAllAuthors" resultType="org.apache.ibatis.domain.blog.Author">
		select * from STUDENTS where 1 = 1
		<choose>
			<when test="name != null">
				and name = #{name}
			when>
			<when test="email != null">
				and EMAIL = #{email}
			when>
			<otherwise>
				and PHONE = "123"
			otherwise>
		choose>
	select>
	


org.apache.ibatis.scripting.xmltags.XMLScriptBuilder.nodeHandlers(String)部分源码

  NodeHandler nodeHandlers(String nodeName) {
    Map<String, NodeHandler> map = new HashMap<String, NodeHandler>();
    map.put("trim", new TrimHandler());
    map.put("where", new WhereHandler());
    map.put("set", new SetHandler());
    map.put("foreach", new ForEachHandler());
    map.put("if", new IfHandler());
    map.put("choose", new ChooseHandler());
    map.put("when", new IfHandler());
    map.put("otherwise", new OtherwiseHandler());
    map.put("bind", new BindHandler());
    return map.get(nodeName);
  }


// 采用组合设计模式
public interface SqlNode {

    /**
     * 应用当前 SQL Node 节点
     *
     * @param context 上下文
     * @return 当前 SQL Node 节点是否应用成功。
     */
    boolean apply(DynamicContext context);

}

    /**
     * `` 标签的处理器
     *
     * @see ChooseSqlNode
     */
    private class ChooseHandler implements NodeHandler {

        public ChooseHandler() {
            // Prevent Synthetic Access
        }

        @Override
        public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) {
            List<SqlNode> whenSqlNodes = new ArrayList<>();
            List<SqlNode> otherwiseSqlNodes = new ArrayList<>();
            // 解析 `` 和 `` 的节点们
            handleWhenOtherwiseNodes(nodeToHandle, whenSqlNodes, otherwiseSqlNodes);
            // 获得 `` 的节点
            SqlNode defaultSqlNode = getDefaultSqlNode(otherwiseSqlNodes);
            // 创建 ChooseSqlNode 对象
            ChooseSqlNode chooseSqlNode = new ChooseSqlNode(whenSqlNodes, defaultSqlNode);
            // 添加到 targetContents 中
            targetContents.add(chooseSqlNode);
        }

        private void handleWhenOtherwiseNodes(XNode chooseSqlNode, List<SqlNode> ifSqlNodes, List<SqlNode> defaultSqlNodes) {
            List<XNode> children = chooseSqlNode.getChildren();
            for (XNode child : children) {
                String nodeName = child.getNode().getNodeName();
                NodeHandler handler = nodeHandlerMap.get(nodeName);
                if (handler instanceof IfHandler) { // 处理 `` 标签的情况
                    handler.handleNode(child, ifSqlNodes);
                } else if (handler instanceof OtherwiseHandler) { // 处理 `` 标签的情况
                    handler.handleNode(child, defaultSqlNodes);
                }
            }
        }

        // 至多允许有一个 SqlNode 节点
        private SqlNode getDefaultSqlNode(List<SqlNode> defaultSqlNodes) {
            SqlNode defaultSqlNode = null;
            if (defaultSqlNodes.size() == 1) {
                defaultSqlNode = defaultSqlNodes.get(0);
            } else if (defaultSqlNodes.size() > 1) {
                throw new BuilderException("Too many default (otherwise) elements in choose statement.");
            }
            return defaultSqlNode;
        }
    }

}
select节点解析涉及到的主要类图

mybatis源码解读二动态sql标签解析_第1张图片

xml解析之后的sqlNode结构

mybatis源码解读二动态sql标签解析_第2张图片

你可能感兴趣的:(mybatis)