Mybatis 动态SQL之<trim>,<where>,<set>源码解析
2017-12-06 21:37
453 查看
Mybatis的trim,where,set这几个sql节点能动态的去除sql片段的前缀或后缀,我们先来看解析trim节点的代码:
以上就是trm的解析逻辑,看代码容易明白。
set和where节点解析类继承TrimSqlNode 。
set的解析逻辑相对trim来说,仅仅只是指定了prefix = SET,suffixesToOverride = “,”,也就是说sql加个前缀SET,如果sql以”,”结尾删除最后一个”,”;
where的解析逻辑相对trim来说,仅仅只是指定了prefi = WHERE,prefixesToOverride= AND | OR,也就是说sql加个前缀WHERE,如果sql以”AND”或者”OR”开始删除开始的”AND”或者”OR”;
public class TrimSqlNode implements SqlNode { private SqlNode contents; private String prefix; private String suffix; private List<String> prefixesToOverride; //可被覆盖的前缀集合,可以在trim节点内指定多个 private List<String> suffixesToOverride; //可被覆盖的后缀集合,可以在trim节点内指定多个 private 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 = new FilteredDynamicContext(context); boolean result = contents.apply(filteredDynamicContext); //这个方法是主要方法,执行此方法,根据给的参数解析内部的if节点,生成sql字符串 filteredDynamicContext.applyAll(); //当内部的if或者其他节点解析完毕后,解析自身trim节点 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<String>(parser.countTokens()); while (parser.hasMoreTokens()) { list.add(parser.nextToken().toUpperCase(Locale.ENGLISH)); } return list; } return Collections.emptyList(); } private class FilteredDynamicContext extends DynamicContext { private DynamicContext delegate; private boolean prefixApplied; private boolean suffixApplied; 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() { sqlBuffer = new StringBuilder(sqlBuffer.toString().trim()); String trimmedUppercaseSql = sqlBuffer.toString().toUpperCase(Locale.ENGLISH); if (trimmedUppercaseSql.length() > 0) { applyPrefix(sqlBuffer, trimmedUppercaseSql); //解析前缀 applySuffix(sqlBuffer, trimmedUppercaseSql); //解析后缀 } 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) { for (String toRemove : prefixesToOverride) { if (trimmedUppercaseSql.startsWith(toRemove)) { sql.delete(0, toRemove.trim().length()); //如果内部节点解析后生成的sql存在prefixOverrides,删除prefixOverrides break; } } } if (prefix != null) { //当指定了prefix时,在sql的最开始处加上prefix 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); //sql以suffixOverrides结尾时,删除suffixOverrides break; } } } if (suffix != null) { //当指定了suffix ,在sql结尾加上suffix sql.append(" "); sql.append(suffix); } } } } }
以上就是trm的解析逻辑,看代码容易明白。
set和where节点解析类继承TrimSqlNode 。
set的解析逻辑相对trim来说,仅仅只是指定了prefix = SET,suffixesToOverride = “,”,也就是说sql加个前缀SET,如果sql以”,”结尾删除最后一个”,”;
where的解析逻辑相对trim来说,仅仅只是指定了prefi = WHERE,prefixesToOverride= AND | OR,也就是说sql加个前缀WHERE,如果sql以”AND”或者”OR”开始删除开始的”AND”或者”OR”;
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); } } 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); } }
相关文章推荐
- Mybatis 最强大的动态sql <where>标签
- mybatis <where>、<set>、<trim>、<sql>、<foreach>标签的使用
- mybatis中<where>标签、<set>标签、<trim>标签、<sql>标签、<foreach>标签的使用
- Mybatis的<where><trim><set>标签使用和排重
- Mybatis的<where><foreach><set><trim>等标签详解
- Mybatis中的三个标签<where> <set> <trim>
- MyBatis动态SQL <trim></trim>标签的明白理解
- mybatis <where>、<set>、<trim>、<sql>、<foreach>标签的使用
- Mybatis的<where><foreach><set>标签详解
- mybatis <where>、<set>、<trim>、<sql>、<foreach>标签的使用
- Mybatis的<where><foreach><set>等标签详解
- Mybatis的<where><foreach><set>等标签详解
- mybatis(ibatis)中的动态sql<dynamic prepend="where"><isNotEmpty>的讲解
- Mybatis最入门---动态查询( <trim prefix="where" prefixOverrides="and|or"> )
- mybatis动态SQL的<where>标签
- mybatis学习之路----动态sql之trim标签源码详解,附带where标签解析
- Mybatis的<where><foreach><set>等标签详解
- 17、动态SQL之<trim>
- Mybatis <where> <if> <set> <trim> <choose>标签
- Mybatis的<where><foreach><set>等标签详解