淺析Mybatis的SqlSource

在以前的博文中我已經說了SqlSource接口的做用,以及StaticSqlSource,具體參考 Mybatis初始化的builder建造者模式 ,這裏主要要說明一下SqlSource接口的另外兩個實現類DynamicSqlSource,RowSqlSource.sql

DynamicSqlSource的接口方法以下app

private final SqlNode rootSqlNode; //記錄待解析的SqlNode的根節點,在構造函數中引入
@Override
public BoundSql getBoundSql(Object parameterObject) {
  //建立DynamicContext對象,parameterObject爲用戶傳入的實參
  DynamicContext context = new DynamicContext(configuration, parameterObject);
  //從根節點開始,解析根節點下的全部子節點獲得的SQL片斷追加到context中,最終經過context.getSql()獲得完整的SQL語句,這是組合模式最大的好處
  rootSqlNode.apply(context);
  //建立SqlSourceBuilder對象,解析參數屬性,將SQL語句中的"#{}"解析成"?"佔位符
  SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
  Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
  SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
  //建立BoundSql對象,並將DynamicContext.bindings中參數信息複製到其additionalParameters集合中保存
  BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
  for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) {
    boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
  }
  return boundSql;
}

RawSqlSource是SqlSource的另外一個實現,邏輯與DynamicSqlSource相似,可是執行時機不一樣,處理的SQL語句類型也不一樣,在XMLScriptBuilder.parseDynamicTags()方法中,若是節點只包含"#{}"佔位符,不包含動態SQL節點或未解析的"${}"佔位符,則不是動態SQL語句,會建立StaticTextSqlNode對象。在XMLScriptBuilder.parseSciptNode()方法中會判斷整個SQL節點是否爲動態節點,若是不是動態SQL節點,則建立響應的RawSqlSource對象。ide

public class RawSqlSource implements SqlSource {

  private final SqlSource sqlSource; //StaticSqlSource對象

  public RawSqlSource(Configuration configuration, SqlNode rootSqlNode, Class<?> parameterType) {
    //調用getSql方法,完成SQL語句的拼裝和初步解析,與DynamicSqlSource中相同
    this(configuration, getSql(configuration, rootSqlNode), parameterType);
  }

  public RawSqlSource(Configuration configuration, String sql, Class<?> parameterType) {
    //經過SqlSourceBuilder完成佔位符的解析和替換操做
    SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
    Class<?> clazz = parameterType == null ? Object.class : parameterType;
    //返回StaticSqlSource
    sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap<String, Object>());
  }

  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);
}

}
相關文章
相關標籤/搜索