MyBatis源码解析--加载流程(4)

接下来是解析sql语句,对应的是scripting包,实现了动态SQL语句的功能。
LanguageDriver 语言驱动接口

public interface LanguageDriver {
//创建ParameterHandler对象
  ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql);
//创建sqlSource,从xml配置中。
  SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType);
//创建sqlSource,从方法注解配置,即@Select
  SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType);

}

XMLLanguageDriver xml语言驱动实现类

public class XMLLanguageDriver implements LanguageDriver {

  @Override
  public ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
    return new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);
  }

  @Override
  //解析xml文件中的sql语句并封装成SqlSource
  public SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) {
    XMLScriptBuilder builder = new XMLScriptBuilder(configuration, script, parameterType);
    return builder.parseScriptNode();
  }

  @Override
  public SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType) {
  //如果是<script>开头就使用xml配置的方法。使用动态SQL
    if (script.startsWith("<script>")) {
    //创建XPathParser对象解析<script>节点
      XPathParser parser = new XPathParser(script, false, configuration.getVariables(), new XMLMapperEntityResolver());
      //使用xml配置的解析方式来生成sqlSource
      return createSqlSource(configuration, parser.evalNode("/script"), parameterType);
    } else {
    //变量更换
      script = PropertyParser.parse(script, configuration.getVariables());
      //创建TextSqlNode对象
      TextSqlNode textSqlNode = new TextSqlNode(script);
      //如果是动态 SQL ,则创建 DynamicSqlSource 对象
      if (textSqlNode.isDynamic()) {
        return new DynamicSqlSource(configuration, textSqlNode);
      } else {
      //如果非动态 SQL ,则创建 RawSqlSource 对象
        return new RawSqlSource(configuration, script, parameterType);
      }
    }
  }
}

RawLanguageDriver RawSqlSource 语言驱动器实现类,确保创建的 SqlSource 是 RawSqlSource 类,XMLLanguageDriver的子类

public class RawLanguageDriver extends XMLLanguageDriver {

  @Override
  public SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) {
    SqlSource source = super.createSqlSource(configuration, script, parameterType);
    //检验创建的是否是RawSqlSource对象
    checkIsNotDynamic(source);
    return source;
  }

  @Override
  public SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType) {
    SqlSource source = super.createSqlSource(configuration, script, parameterType);
    // 校验创建的是 RawSqlSource 对象
    checkIsNotDynamic(source);
    return source;
  }
//如果是动态sql会抛出异常
  private void checkIsNotDynamic(SqlSource source) {
    if (!RawSqlSource.class.equals(source.getClass())) {
      throw new BuilderException("Dynamic content is not allowed when using RAW language");
    }
  }
}

LanguageDriverRegistry LanguageDriver 注册表

public class LanguageDriverRegistry {
//LanguageDriver映射
  private final Map<Class<? extends LanguageDriver>, LanguageDriver> LANGUAGE_DRIVER_MAP = new HashMap<>();
//默认的 LanguageDriver 类
  private Class<? extends LanguageDriver> defaultDriverClass;
//注册类
  public void register(Class<? extends LanguageDriver> cls) {
    if (cls == null) {
      throw new IllegalArgumentException("null is not a valid Language Driver");
    }
    //判断原来map中没有
    if (!LANGUAGE_DRIVER_MAP.containsKey(cls)) {
      try {
      //将实例放入map
        LANGUAGE_DRIVER_MAP.put(cls, cls.newInstance());
      } catch (Exception ex) {
        throw new ScriptingException("Failed to load language driver for " + cls.getName(), ex);
      }
    }
  }
//注册实例
  public void register(LanguageDriver instance) {
    if (instance == null) {
      throw new IllegalArgumentException("null is not a valid Language Driver");
    }
    Class<? extends LanguageDriver> cls = instance.getClass();
    if (!LANGUAGE_DRIVER_MAP.containsKey(cls)) {
      LANGUAGE_DRIVER_MAP.put(cls, instance);
    }
  }
  //获得类对应的实例
  public LanguageDriver getDriver(Class<? extends LanguageDriver> cls) {
    return LANGUAGE_DRIVER_MAP.get(cls);
  }
//获得默认的Driver
  public LanguageDriver getDefaultDriver() {
    return getDriver(getDefaultDriverClass());
  }

  public Class<? extends LanguageDriver> getDefaultDriverClass() {
    return defaultDriverClass;
  }

  public void setDefaultDriverClass(Class<? extends LanguageDriver> defaultDriverClass) {
    register(defaultDriverClass);
    this.defaultDriverClass = defaultDriverClass;
  }

}

在Configuration的构造函数中会调用注册方法:

//往map中注册了两个LanguageDriver,其中XMLLanguageDriver是默认的LanguageDriver
languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
    languageRegistry.register(RawLanguageDriver.class);

XMLScriptBuilder 同样继承于BaseBuilder,负责将SQL解析成SqlSource对象

public class XMLScriptBuilder extends BaseBuilder {
//当前SQL的XNode对象
  private final XNode context;
  //是否为动态SQL
  private boolean isDynamic;
  //SQL方法类型
  private final Class<?> parameterType;
  //NodeHandler的映射
  private final Map<String, NodeHandler> nodeHandlerMap = new HashMap<>();

  public XMLScriptBuilder(Configuration configuration, XNode context) {
    this(configuration, context, null);
  }

  public XMLScriptBuilder(Configuration configuration, XNode context, Class<?> parameterType) {
    super(configuration);
    this.context = context;
    this.parameterType = parameterType;
    //初始化nodeHandlerMap 属性
    initNodeHandlerMap();
  }

//往map中注册各种处理器
  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());
  }

  //解析sql脚本,返回SqlSource
  public SqlSource parseScriptNode() {
    MixedSqlNode rootSqlNode = parseDynamicTags(context);
    SqlSource sqlSource = null;
    if (isDynamic) {
      sqlSource = new DynamicSqlSource(configuration, rootSqlNode);//动态sql的解析
    } else {
      sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);//非动态sql的解析
    }
    //实际返回的都是StaticSqlSource,可以直接让数据库执行的sql语句,包含?占位符
    return sqlSource;
  }
//将SQL解析成MixedSqlNode对象
  protected MixedSqlNode parseDynamicTags(XNode node) {
  //创建SqlNode数组
    List<SqlNode> contents = new ArrayList<>();
    //遍历Sql节点的所有子节点
    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 textSqlNode = new TextSqlNode(data);
        //如果是动态的TextSqlNode对象
        if (textSqlNode.isDynamic()) {
        //添加到contents中
          contents.add(textSqlNode);
          isDynamic = true;
        } else {
        //创建静态的TextSqlNode添加到contents中
          contents.add(new StaticTextSqlNode(data));
        }
        //如果是元素节点
      } else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { 
      //根据子节点的标签获得对应的NodeHandler对象
        String nodeName = child.getNode().getNodeName();
        NodeHandler handler = nodeHandlerMap.get(nodeName);
        if (handler == null) {
          throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement.");
        }
        //处理NodeHandler对象
        handler.handleNode(child, contents);
        //标记为动态Sql
        isDynamic = true;
      }
    }
    //根据SqlNode数组来创建MixedSqlNode对象
    return new MixedSqlNode(contents);
  }
//NodeHandler是内部接口,Node处理器接口
  private interface NodeHandler {
  //处理接口
    void handleNode(XNode nodeToHandle, List<SqlNode> targetContents);
  }
//<bind>标签的处理器
  private class BindHandler implements NodeHandler {
    public BindHandler() {
      // Prevent Synthetic Access
    }

    @Override
    public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) {
    //取出name属性的值
      final String name = nodeToHandle.getStringAttribute("name");
      //取出value属性的值
      final String expression = nodeToHandle.getStringAttribute("value");
      // 创建 VarDeclSqlNode 对象
      final VarDeclSqlNode node = new VarDeclSqlNode(name, expression);
      // 添加到 targetContents 中
      targetContents.add(node);
    }
  }
//
  private class TrimHandler implements NodeHandler {
    public TrimHandler() {
      // Prevent Synthetic Access
    }
//<trim>标签的处理器
    @Override
    public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) {
    //解析内部的 SQL 节点,成 MixedSqlNode 对象
      MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle);
      //获得 prefix、prefixOverrides、suffix、suffixOverrides 属性
      String prefix = nodeToHandle.getStringAttribute("prefix");
      String prefixOverrides = nodeToHandle.getStringAttribute("prefixOverrides");
      String suffix = nodeToHandle.getStringAttribute("suffix");
      String suffixOverrides = nodeToHandle.getStringAttribute("suffixOverrides");
      //创建TrimSqlNode对象
      TrimSqlNode trim = new TrimSqlNode(configuration, mixedSqlNode, prefix, prefixOverrides, suffix, suffixOverrides);
      //添加到targetContents中
      targetContents.add(trim);
    }
  }
//处理<where>标签
  private class WhereHandler implements NodeHandler {
    public WhereHandler() {
      // Prevent Synthetic Access
    }

    @Override
    public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) {
    //解析内部的SQL节点成MixedSqlNode
      MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle);
      //创建WhereSqlNode对象
      WhereSqlNode where = new WhereSqlNode(configuration, mixedSqlNode);
      targetContents.add(where);
    }
  }
//处理<set>标签
  private class SetHandler implements NodeHandler {
    public SetHandler() {
      // Prevent Synthetic Access
    }
    @Override
    public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) {
    //解析内部的SQL节点成MixedSqlNode对象
      MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle);
      // 创建 SetSqlNode 对象
      SetSqlNode set = new SetSqlNode(configuration, mixedSqlNode);
      targetContents.add(set);
    }
  }
//<foreach /> 标签的处理器
  private class ForEachHandler implements NodeHandler {
    public ForEachHandler() {
      // Prevent Synthetic Access
    }

    @Override
    public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) {
    // 解析内部的 SQL 节点,成 MixedSqlNode 对象
      MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle);
      // 获得 collection、item、index、open、close、separator 属性
      String collection = nodeToHandle.getStringAttribute("collection");
      String item = nodeToHandle.getStringAttribute("item");
      String index = nodeToHandle.getStringAttribute("index");
      String open = nodeToHandle.getStringAttribute("open");
      String close = nodeToHandle.getStringAttribute("close");
      String separator = nodeToHandle.getStringAttribute("separator");
      // 创建 ForEachSqlNode 对象
      ForEachSqlNode forEachSqlNode = new ForEachSqlNode(configuration, mixedSqlNode, collection, index, item, open, close, separator);
      targetContents.add(forEachSqlNode);
    }
  }
//<if /> 标签的处理器
  private class IfHandler implements NodeHandler {
    public IfHandler() {
      // Prevent Synthetic Access
    }

    @Override
    public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) {
    // 解析内部的 SQL 节点,成 MixedSqlNode 对象
      MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle);
      String test = nodeToHandle.getStringAttribute("test");
      // 创建 IfSqlNode 对象
      IfSqlNode ifSqlNode = new IfSqlNode(mixedSqlNode, test);
      targetContents.add(ifSqlNode);
    }
  }
//<otherwise /> 标签的处理器
  private class OtherwiseHandler implements NodeHandler {
    public OtherwiseHandler() {
      // Prevent Synthetic Access
    }

    @Override
    public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) {
    // 解析内部的 SQL 节点,成 MixedSqlNode 对象
      MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle);
      // 添加到 targetContents 中
      targetContents.add(mixedSqlNode);
    }
  }
//<choose /> 标签的处理器
  private class ChooseHandler implements NodeHandler {
    public ChooseHandler() {
      // Prevent Synthetic Access
    }

    @Override
    public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) {
    //创建两个list,一个是when属性,一个是otherwise属性
      List<SqlNode> whenSqlNodes = new ArrayList<>();
      List<SqlNode> otherwiseSqlNodes = new ArrayList<>();
      // 解析 `<when />` 和 `<otherwise />` 的节点们
      handleWhenOtherwiseNodes(nodeToHandle, whenSqlNodes, otherwiseSqlNodes);
      // 获得 `<otherwise />` 的节点
      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) {
       //处理when的情况
          handler.handleNode(child, ifSqlNodes);
        } else if (handler instanceof OtherwiseHandler) {
        //处理otherwise情况
          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;
    }
  }

}

DynamicContext 动态SQL,每次执行SQL操作时,记录动态SQL处理后的最终SQL字符串。

public class DynamicContext {
//_parameter的键
  public static final String PARAMETER_OBJECT_KEY = "_parameter";
  //_databaseId 的键
  public static final String DATABASE_ID_KEY = "_databaseId";

  static {
  //设置OGNL的属性访问器
    OgnlRuntime.setPropertyAccessor(ContextMap.class, new ContextAccessor());
  }
//上下文参数集合
  private final ContextMap bindings;
  //生成后的SQL
  private final StringBuilder sqlBuilder = new StringBuilder();
  //唯一编号
  private int uniqueNumber = 0;
//如果使用到OGNL,ParameterObject为非空
  public DynamicContext(Configuration configuration, Object parameterObject) {
    if (parameterObject != null && !(parameterObject instanceof Map)) {
      MetaObject metaObject = configuration.newMetaObject(parameterObject);
      bindings = new ContextMap(metaObject);
    } else {
      bindings = new ContextMap(null);
    }
    //添加bindings的默认值
    bindings.put(PARAMETER_OBJECT_KEY, parameterObject);
    bindings.put(DATABASE_ID_KEY, configuration.getDatabaseId());
  }

  public Map<String, Object> getBindings() {
    return bindings;
  }

  public void bind(String name, Object value) {
    bindings.put(name, value);
  }
//拼接sql
  public void appendSql(String sql) {
    sqlBuilder.append(sql);
    sqlBuilder.append(" ");
  }
//获得sql
  public String getSql() {
    return sqlBuilder.toString().trim();
  }
//每次请求获得新的序号
  public int getUniqueNumber() {
    return uniqueNumber++;
  }
//内部静态类
  static class ContextMap extends HashMap<String, Object> {
    private static final long serialVersionUID = 2977601501966151582L;
//parameter对应的MetaObject对象
    private MetaObject parameterMetaObject;
    public ContextMap(MetaObject parameterMetaObject) {
      this.parameterMetaObject = parameterMetaObject;
    }

    @Override
    public Object get(Object key) {
      String strKey = (String) key;
      if (super.containsKey(strKey)) {
        return super.get(strKey);
      }

      if (parameterMetaObject != null) {
        // issue #61 do not modify the context when reading
        return parameterMetaObject.getValue(strKey);
      }

      return null;
    }
  }
//上下文访问器
  static class ContextAccessor implements PropertyAccessor {

    @Override
    public Object getProperty(Map context, Object target, Object name)
        throws OgnlException {
      Map map = (Map) target;
// 优先从 ContextMap 中,获得属性
      Object result = map.get(name);
      if (map.containsKey(name) || result != null) {
        return result;
      }
// 如果没有,则从 PARAMETER_OBJECT_KEY 对应的 Map 中,获得属性
      Object parameterObject = map.get(PARAMETER_OBJECT_KEY);
      if (parameterObject instanceof Map) {
        return ((Map)parameterObject).get(name);
      }

      return null;
    }

    @Override
    public void setProperty(Map context, Object target, Object name, Object value)
        throws OgnlException {
      Map<Object, Object> map = (Map<Object, Object>) target;
      map.put(name, value);
    }

    @Override
    public String getSourceAccessor(OgnlContext arg0, Object arg1, Object arg2) {
      return null;
    }

    @Override
    public String getSourceSetter(OgnlContext arg0, Object arg1, Object arg2) {
      return null;
    }
  }
}

SqlNode SQL Node 接口,每个 XML Node 会解析成对应的 SQL Node 对象

public interface SqlNode {
//应用当前的SQL  Node节点
  boolean apply(DynamicContext context);
}

VarDeclSqlNode bind标签的实现类

public class VarDeclSqlNode implements SqlNode {

  private final String name;
  private final String expression;

  public VarDeclSqlNode(String var, String exp) {
    name = var;
    expression = exp;
  }

  @Override
  public boolean apply(DynamicContext context) {
  //获得值 
    final Object value = OgnlCache.getValue(expression, context.getBindings());
    //绑定到上下文
    context.bind(name, value);
    return true;
  }

TrimSqlNode trim标签的SqlNode实现类

public class TrimSqlNode implements SqlNode {
//内含的SqlNode节点
  private final SqlNode contents;
  //前缀
  private final String prefix;
  //后缀
  private final String suffix;
  //需要被删除的前缀
  private final List<String> prefixesToOverride;
  //需要被删除的后缀
  private final List<String> suffixesToOverride;
  private final Configuration configuration;
//构造函数
  public TrimSqlNode(Configuration configuration, SqlNode contents, String prefix, String prefixesToOverride, String suffix, String suffixesToOverride) {
    this(configuration, contents, prefix, parseOverrides(prefixesToOverride), suffix, parseOverrides(suffixesToOverride));
  }

  protected TrimSqlNode(Configuration configuration, SqlNode contents, String prefix, List<String> prefixesToOverride, String suffix, List<String> suffixesToOverride) {
    this.contents = contents;
    this.prefix = prefix;
    this.prefixesToOverride = prefixesToOverride;
    this.suffix = suffix;
    this.suffixesToOverride = suffixesToOverride;
    this.configuration = configuration;
  }

  @Override
  public boolean apply(DynamicContext context) {
  //创建FilteredDynamicContext对象
    FilteredDynamicContext filteredDynamicContext = new FilteredDynamicContext(context);
    //执行contents的应用
    boolean result = contents.apply(filteredDynamicContext);
    //执行FilteredDynamicContext的应用
    filteredDynamicContext.applyAll();
    return result;
  }
//使用|分割字符串成字符串数组并且都转换成大写
  private static List<String> parseOverrides(String overrides) {
    if (overrides != null) {
      final StringTokenizer parser = new StringTokenizer(overrides, "|", false);
      final List<String> list = new ArrayList<>(parser.countTokens());
      while (parser.hasMoreTokens()) {
        list.add(parser.nextToken().toUpperCase(Locale.ENGLISH));
      }
      return list;
    }
    return Collections.emptyList();
  }
//内部类
  private class FilteredDynamicContext extends DynamicContext {
  //委托的DynamicContext对象
    private DynamicContext delegate;
    //prefix是否已经被应用
    private boolean prefixApplied;
    //suffix是否已经被应用
    private boolean suffixApplied;
    //StringBuilder对象
    private StringBuilder sqlBuffer;

    public FilteredDynamicContext(DynamicContext delegate) {
      super(configuration, null);
      this.delegate = delegate;
      this.prefixApplied = false;
      this.suffixApplied = false;
      this.sqlBuffer = new StringBuilder();
    }

    public void applyAll() {
    //trim去除多余的空格,生成新的sqlBuffer对象
      sqlBuffer = new StringBuilder(sqlBuffer.toString().trim());
     //将sqlBuffer大写,生成新的trimmedUppercaseSql
      String trimmedUppercaseSql = sqlBuffer.toString().toUpperCase(Locale.ENGLISH);
      //应用TrimSqlNode的trim逻辑
      if (trimmedUppercaseSql.length() > 0) {
        applyPrefix(sqlBuffer, trimmedUppercaseSql);
        applySuffix(sqlBuffer, trimmedUppercaseSql);
      }
      //将结果添加到delegate中
      delegate.appendSql(sqlBuffer.toString());
    }

    @Override
    public Map<String, Object> getBindings() {
      return delegate.getBindings();
    }

    @Override
    public void bind(String name, Object value) {
      delegate.bind(name, value);
    }

    @Override
    public int getUniqueNumber() {
      return delegate.getUniqueNumber();
    }

    @Override
    public void appendSql(String sql) {
      sqlBuffer.append(sql);
    }

    @Override
    public String getSql() {
      return delegate.getSql();
    }

    private void applyPrefix(StringBuilder sql, String trimmedUppercaseSql) {
      if (!prefixApplied) {
        prefixApplied = true;
        if (prefixesToOverride != null) {
        //遍历,如果发现开头是指定的prefixtooverride就删除
          for (String toRemove : prefixesToOverride) {
            if (trimmedUppercaseSql.startsWith(toRemove)) {
              sql.delete(0, toRemove.trim().length());
              break;
            }
          }
        }
        //非空再添加
        if (prefix != null) {
          sql.insert(0, " ");
          sql.insert(0, prefix);
        }
      }
    }

    private void applySuffix(StringBuilder sql, String trimmedUppercaseSql) {
      if (!suffixApplied) {
        suffixApplied = true;
        if (suffixesToOverride != null) {
          for (String toRemove : suffixesToOverride) {
            if (trimmedUppercaseSql.endsWith(toRemove) || trimmedUppercaseSql.endsWith(toRemove.trim())) {
              int start = sql.length() - toRemove.trim().length();
              int end = sql.length();
              sql.delete(start, end);
              break;
            }
          }
        }
        if (suffix != null) {
          sql.append(" ");
          sql.append(suffix);
        }
      }
    }

  }

}

WhereSqlNode 其实就是TrimSqlNode的一个应用

public class WhereSqlNode extends TrimSqlNode {

  private static List<String> prefixList = Arrays.asList("AND ","OR ","AND\n", "OR\n", "AND\r", "OR\r", "AND\t", "OR\t");

  public WhereSqlNode(Configuration configuration, SqlNode contents) {
    super(configuration, contents, "WHERE", prefixList, null, null);
  }

}

SetSqlNode 同样的也是TrimSqlNode的一个应用,set标签的实现类

public class SetSqlNode extends TrimSqlNode {

  private static List<String> suffixList = Arrays.asList(",");

  public SetSqlNode(Configuration configuration,SqlNode contents) {
    super(configuration, contents, "SET", null, null, suffixList);
  }

}

ForEachSqlBNode foreach标签的实现类

public class ForEachSqlNode implements SqlNode {
  public static final String ITEM_PREFIX = "__frch_";

  private final ExpressionEvaluator evaluator;
  private final String collectionExpression;
  private final SqlNode contents;
  private final String open;
  private final String close;
  private final String separator;
  //项
  private final String item;
  //索引
  private final String index;
  private final Configuration configuration;
//构造函数
  public ForEachSqlNode(Configuration configuration, SqlNode contents, String collectionExpression, String index, String item, String open, String close, String separator) {
    this.evaluator = new ExpressionEvaluator();
    this.collectionExpression = collectionExpression;
    this.contents = contents;
    this.open = open;
    this.close = close;
    this.separator = separator;
    this.index = index;
    this.item = item;
    this.configuration = configuration;
  }

  @Override
  public boolean apply(DynamicContext context) {
    Map<String, Object> bindings = context.getBindings();
    //获得集合iterable对象,用于遍历
    final Iterable<?> iterable = evaluator.evaluateIterable(collectionExpression, bindings);
    if (!iterable.iterator().hasNext()) {
      return true;
    }
    boolean first = true;
    //添加open到sql
    applyOpen(context);
    int i = 0;
    for (Object o : iterable) {
    //记录原始的context对象
      DynamicContext oldContext = context;
      //生成新的context
      if (first || separator == null) {
        context = new PrefixedContext(context, "");
      } else {
        context = new PrefixedContext(context, separator);
      }
      //获得唯一的编号
      int uniqueNumber = context.getUniqueNumber();
      // Issue #709 
      //绑定到context
      if (o instanceof Map.Entry) {
        @SuppressWarnings("unchecked") 
        Map.Entry<Object, Object> mapEntry = (Map.Entry<Object, Object>) o;
        applyIndex(context, mapEntry.getKey(), uniqueNumber);
        applyItem(context, mapEntry.getValue(), uniqueNumber);
      } else {
        applyIndex(context, i, uniqueNumber);
        applyItem(context, o, uniqueNumber);
      }
      //执行contents的应用
      contents.apply(new FilteredDynamicContext(configuration, context, index, item, uniqueNumber));
      if (first) {
        first = !((PrefixedContext) context).isPrefixApplied();
      }
      context = oldContext;
      i++;
    }
    //添加close到SQL中
    applyClose(context);
    //移除index和item对应的绑定
    context.getBindings().remove(item);
    context.getBindings().remove(index);
    return true;
  }

  private void applyIndex(DynamicContext context, Object o, int i) {
    if (index != null) {
      context.bind(index, o);
      context.bind(itemizeItem(index, i), o);
    }
  }

  private void applyItem(DynamicContext context, Object o, int i) {
    if (item != null) {
      context.bind(item, o);
      context.bind(itemizeItem(item, i), o);
    }
  }

  private void applyOpen(DynamicContext context) {
    if (open != null) {
      context.appendSql(open);
    }
  }

  private void applyClose(DynamicContext context) {
    if (close != null) {
      context.appendSql(close);
    }
  }

  private static String itemizeItem(String item, int i) {
    return ITEM_PREFIX + item + "_" + i;
  }
//内部类。实现变量的替换
  private static class FilteredDynamicContext extends DynamicContext {
    private final DynamicContext delegate;
    private final int index;
    private final String itemIndex;
    private final String item;

    public FilteredDynamicContext(Configuration configuration,DynamicContext delegate, String itemIndex, String item, int i) {
      super(configuration, null);
      this.delegate = delegate;
      this.index = i;
      this.itemIndex = itemIndex;
      this.item = item;
    }

    @Override
    public Map<String, Object> getBindings() {
      return delegate.getBindings();
    }

    @Override
    public void bind(String name, Object value) {
      delegate.bind(name, value);
    }

    @Override
    public String getSql() {
      return delegate.getSql();
    }

    @Override
    public void appendSql(String sql) {
      GenericTokenParser parser = new GenericTokenParser("#{", "}", content -> {
      //将对于item的访问替换成对于itemizeItem的访问
        String newContent = content.replaceFirst("^\\s*" + item + "(?![^.,:\\s])", itemizeItem(item, index));
        //将对于itemIndex的访问替换成对于itemizeItem的访问
        if (itemIndex != null && newContent.equals(content)) {
          newContent = content.replaceFirst("^\\s*" + itemIndex + "(?![^.,:\\s])", itemizeItem(itemIndex, index));
        }
        return "#{" + newContent + "}";
      });

      delegate.appendSql(parser.parse(sql));
    }

    @Override
    public int getUniqueNumber() {
      return delegate.getUniqueNumber();
    }

  }

//内部类,支持添加foreach标签中多个元素之间的分隔符的DynamicContext实现类
  private class PrefixedContext extends DynamicContext {
    private final DynamicContext delegate;
    //其实是separator属性
    private final String prefix;
    //是否已经应用prefix
    private boolean prefixApplied;

    public PrefixedContext(DynamicContext delegate, String prefix) {
      super(configuration, null);
      this.delegate = delegate;
      this.prefix = prefix;
      this.prefixApplied = false;
    }

    public boolean isPrefixApplied() {
      return prefixApplied;
    }

    @Override
    public Map<String, Object> getBindings() {
      return delegate.getBindings();
    }

    @Override
    public void bind(String name, Object value) {
      delegate.bind(name, value);
    }

    @Override
    public void appendSql(String sql) {
    //如果没有应用prefix并且方法参数sql非空,则添加prefix 到 delegate 中
      if (!prefixApplied && sql != null && sql.trim().length() > 0) {
        delegate.appendSql(prefix);
        prefixApplied = true;
      }
      delegate.appendSql(sql);
    }

    @Override
    public String getSql() {
      return delegate.getSql();
    }

    @Override
    public int getUniqueNumber() {
      return delegate.getUniqueNumber();
    }
  }

}

IfSqlNode if标签的SqlNode实现类

public class IfSqlNode implements SqlNode {
  private final ExpressionEvaluator evaluator;
  //判断表达式
  private final String test;
  //内嵌的SqlNode节点
  private final SqlNode contents;

  public IfSqlNode(SqlNode contents, String test) {
    this.test = test;
    this.contents = contents;
    this.evaluator = new ExpressionEvaluator();
  }

  @Override
  public boolean apply(DynamicContext context) {
  //判断是否符合条件
    if (evaluator.evaluateBoolean(test, context.getBindings())) {
    //符合就执行contents的应用
      contents.apply(context);
      return true;
    }
    return false;
  }
}

ChooseSqlNode choose标签的SqlNode实现类

public class ChooseSqlNode implements SqlNode {
//otherwise对应的SqlNode节点
  private final SqlNode defaultSqlNode;
  //when标签对应的SqlNode节点数组
  private final List<SqlNode> ifSqlNodes;

  public ChooseSqlNode(List<SqlNode> ifSqlNodes, SqlNode defaultSqlNode) {
    this.ifSqlNodes = ifSqlNodes;
    this.defaultSqlNode = defaultSqlNode;
  }

  @Override
  public boolean apply(DynamicContext context) {
  //逐个调用when标签,如果有就进行应用,但是只应用一个SqlNode对象
    for (SqlNode sqlNode : ifSqlNodes) {
      if (sqlNode.apply(context)) {
        return true;
      }
    }
    //再判断otherwise是否存在
    if (defaultSqlNode != null) {
      defaultSqlNode.apply(context);
      return true;
    }
    return false;
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值