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