• Mybatis—LanguageDriver


      LanguageDriver主要用于构造SqlSource和ParameterHandler,从LanguageDriver在Mybatis中调用链路来看,Configuration#newParameterHandler通过调用LanguageDriver#createParameterHandler完成构建ParameterHandler,通过调用LanguageDriver#createSqlSource来完成构建SqlSource。
      LanguageDriver接口一共只定义了createParameterHandler和两个createSqlSource方法,其结构也相当简单,Mybatis只实现了RawLanguageDriver和XMLLanguageDriver两个类,且RawLanguageDriver还继承自XMLLanguageDriver,如下图所示。在这里插入图片描述

    • XMLLanguageDriver,XML语言驱动,主要帮助Mybatis实现通过XML标签描述的动态SQL。
    • RawLanguageDriver,与RawSqlSource一样,主要表示支持静态SQL信息配置。

    XMLLanguageDriver

      XMLLanguageDriver以XML打头就已经明确说明该实现主要是为了支持使用XML标签描述的动态SQL,其完整实现了LanguageDriver接口定义的三个方法,其中createParameterHandler方法的实现仅是通过DefaultParameterHandler构造函数构造了一个ParameterHandler,所以就不再做过多的讨论。

    @Override
    public ParameterHandler createParameterHandler(
          MappedStatement mappedStatement, 
          Object parameterObject, BoundSql boundSql) {
        return new DefaultParameterHandler(
            mappedStatement, parameterObject, boundSql);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    createSqlSource

      LanguageDriver接口定了两个createSqlSource方法从源代码来看二则唯一的区别就在于入参的第二个参数,一个接口定义所需要的XNode类型的script,另一个接口定义则需要String类型的script。Mybatis之所以这么设计,是因为一个方法是用于处理通过XML配置的SQL信息,另一个方法则用于处理通过注解配置的SQL信息。

    • 处理XML配置的SQL信息

      从源代码来看,用于处理XML配置的SQL信息的createSqlSource方法逻辑相对清晰,

    @Override
    public SqlSource createSqlSource(
          Configuration configuration, 
          XNode script, Class<?> parameterType) {
        XMLScriptBuilder builder = new XMLScriptBuilder(
            configuration, script, parameterType);
        return builder.parseScriptNode();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1. 通过所传入的参数构建一个用于处理XML配置的XMLScriptBuilder对象;
    2. 调用XMLScriptBuilder#parseScriptNode方法将SQL信息转换为SqlSource对象。

      XMLLanguageDriver使用XMLScriptBuilder来构建了SqlSource对象,由此可见XMLScriptBuilder的职责就是解析XML配置信息构建对应的SqlSource对象,如下源代码所示,XMLScriptBuilder的构造函数在完成对属性赋值之后,又通过initNodeHandlerMap方法初始化了一批针对XML配置标签的处理器。之后在调用XMLScriptBuilder#parseScriptNode方法时通过解析结果中的isDynamic来分别构建DynamicSqlSource和RawSqlSource。

    public XMLScriptBuilder(
        Configuration configuration, 
        XNode context, Class<?> parameterType) {
        super(configuration);
        this.context = context;
        this.parameterType = parameterType;
        initNodeHandlerMap();
    }
    
    private void initNodeHandlerMap() {
        nodeHandlerMap.put("trim", new TrimHandler());
        nodeHandlerMap.put("where", new WhereHandler());
        nodeHandlerMap.put("set", new SetHandler());
        nodeHandlerMap.put("foreach", new ForEachHandler());
        nodeHandlerMap.put("if", new IfHandler());
        nodeHandlerMap.put("choose", new ChooseHandler());
        nodeHandlerMap.put("when", new IfHandler());
        nodeHandlerMap.put("otherwise", new OtherwiseHandler());
        nodeHandlerMap.put("bind", new BindHandler());
    }
    
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 处理注解配置的SQL信息

      处理注解配置的SQL信息的createSqlSource方法有两个处理分支,一个处理script文本中有”)

  • 如果所传入的script文本中不包含