在以前的博文中我已經說了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); } }