最近在学Mybatis,在学到动态sql的trim标签时,很迷惑。不知所以然。看别人的博客和论坛里的解释,太宽泛,还是不能理解:

trim元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是prefix和suffix;可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是prefixOverrides和suffixOverrides;正因为trim有这样的功能,所以我们也可以非常简单的利用trim来代替where元素的功能。

例1:

 <select id="selectUsersTrim" resultMap="resultListUsers" parameterType="Users">
select * from users
<trim prefix="where" prefixOverrides="and">
<if test="name!=null">
name=#{name}
</if>
<if test="address!=null">
and address=#{address}
</if>
</trim>
</select>

可以看到后台打印的sql:

例2:

   <select id="selectUsersTrim" resultMap="resultListUsers" parameterType="Users">
select * from users
<trim prefix="where" prefixOverrides="and">
<if test="name!=null">
or name=#{name}
</if>
<if test="address!=null">
and address=#{address}
</if>
</trim>
</select>

后台报错:

怎么办呢?遇到问题,当然要想办法解决。灵光一闪,我不是把源代码绑定到了mybatis的jar上了吗?对,那就看源代码,源代码还能debug呢,更方便。

trim标签的java方法调用栈轨迹:(只写出关键的几个)

org.apache.ibatis.scripting.xmltags.TrimSqlNode.apply()

org.apache.ibatis.scripting.xmltags.TrimSqlNode.FilteredDynamicContext.applyAll()

org.apache.ibatis.scripting.xmltags.TrimSqlNode.FilteredDynamicContext.applyPrefix()

applyPrefix()的源代码:

代码块1:

  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());
break;
}
}
}
if (prefix != null) {
sql.insert(0, " ");
sql.insert(0, prefix);
}
}
}
prefixApplied的值:初始是false.从下面代码内部类TrimSqlNode.FilteredDynamicContext的构造器可以看出:
代码块2:
 public FilteredDynamicContext(DynamicContext delegate) {
super(configuration, null);
this.delegate = delegate;
this.prefixApplied = false;
this.suffixApplied = false;
this.sqlBuffer = new StringBuilder();
}
List集合类型prefixesToOverride :trim标签的属性prefixOverrides,
String类型prefix:trim标签的属性prefix.
trimmedUppercaseSql:trim标签的子标签里的sql语句.
见下面代码:(TrimSqlNode的成员变量):
代码块3:
   private String prefix;
private String suffix;
private List<String> prefixesToOverride;
private List<String> suffixesToOverride;

现在我们在回看代码块1,会发现整个方法的大致意思:当trim标签prefixOverrides属性不为空时,遍历prefixOverrides集合的值,并且用trim标签里第一个子标签(比如if标签)的sql的语句头去匹配prefixOverrides集合的元素值,一旦匹配成功,则将第一个子标签的sql语句匹配的元素删掉,继续向下运行,判断prefix属性是否有值,若有值,在将prefix的值放到第一个子标签的sql语句开头。

所以,例2,将prefixOverrides的值改为 or  或者 and|or 就行了。

好吧,就是这样,可能是自己的语言表达能力不够水平,感觉还是看代码来的精确 :)

最后在总结下吧:

trim标签的prefixOverrides和prefix分两步骤:

1.如果prefixOverrides有元素,拿元素去匹配 第一个子标签sql语句,若匹配上,就删掉sql语句的匹配部分,跳到2

2.如果prefix有值,就在  第一个子标签sql语句 的最前面加上 prefix的值。

 

Mybatis之trim标签的理解的更多相关文章

  1. Mybatis中trim标签的用法

    select * from t_user <trim prefix="WHERE" prefixOverrides="and"> <if te ...

  2. mybatis : trim标签, “等于==”经验, CDATA标签 ,模糊查询CONCAT,LIKE

    一.My Batis trim标签有点类似于replace效果. trim 属性, prefix:前缀覆盖并增加其内容 suffix:后缀覆盖并增加其内容 prefixOverrides:前缀判断的条 ...

  3. MyBatis动态SQL中trim标签的使用

    My Batis 官方文档 对 动态SQL中使用trim标签的场景及效果介绍比较少. 事实上trim标签有点类似于replace效果. trim 属性 prefix:前缀覆盖并增加其内容 suffix ...

  4. mybatis动态插入数据(使用trim标签)

    知识点: 当向一张表里插入数据,传入的参数不固定时,使用到mybatis的动态插入(trim标签) 参考博客:https://blog.csdn.net/h12kjgj/article/details ...

  5. Mybatis学习笔记11 - 动态sql之trim标签

    trim标签体中是整个字符串拼串后的结果.prefix="" 前缀: prefix给拼串后的整个字符串加一个前缀prefixOverrides="" 前缀覆盖: ...

  6. Mybatis中的ognl表达式。及myabtis where标签/if test标签/trim标签

    1.mybatis默认支持使用ognl表达式来生成动态sql语句 MyBatis中可以使用OGNL的地方有两处: 动态SQL表达式中 ${param}参数中 上面这两处地方在MyBatis中处理的时候 ...

  7. MyBatis where、set、trim标签的用法

    <!-- 4.3.1 where用法 <where>标签的作用:如果该便签包含的元素中有返回值,就插入一个where:如果 where后面的字符串是一and或or开头的,就将它们剔除 ...

  8. MyBatis动态添加—trim标签

    做添加时,部分字段有值,没值的字段不添加,这就是动态添加,使用 trim 标签就可以实现. <insert id="insertSysUser" parameterType= ...

  9. 9.mybatis动态SQL标签的用法

    mybatis动态SQL标签的用法   动态 SQL MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么 ...

随机推荐

  1. 用 JavaScript 将网站后台的数据变化实时更新到前端

    1.ajax短连接:客户端每隔一秒钟发一次请求,服务器收到请求后会立刻返回结果,不管有没有新数据.2.ajax长连接:客户端发送一次请求,服务器端收到请求后查询有没有新数据,如果没有新数据就阻塞这个请 ...

  2. Windows下tomcat启动一闪而过

    1.用记事本打开tomcat/bin/setclasspath.bat 2.添加两行代码,jdk和jre的根目录,相当于直接给出JAVA_HOME和JRE_HOME路径 set JRE_HOME=D: ...

  3. 牛客OI周赛4-提高组 C 战争(war)

    战争(war) 思路: 二分答案, 找到第一个不满足条件的位置 首先对于一个值来说, 所有这个值的区间肯定有交区间, 然后在这个交区间内不能出现比它小的数 所以我们check时从大的值开始考虑, 求出 ...

  4. mybatis-generator使用心得

    通过web service给前端返回数据 首先后台先建表, 再针对表进行CRUD的各种sql, 然鹅,现在流行做法是使用mybatis,直接xml把sql融合了,什么事都有利弊,像我这样的手写sql党 ...

  5. HTML第八章总结

    Expanding your vocabulary 总述 在上一章节介绍了 CSS 的基础之后,这一章节更加具体地展开关于 CSS 的各种 rules 能够达成的效果.比如 字体:font-famil ...

  6. 【简单易懂】JPA概念解析:CascadeType(各种级联操作)详解

    https://www.jianshu.com/p/e8caafce5445 [在一切开始之前,我要先告诉大家:慎用级联关系,不要随便给all权限操作.应该根据业务需求选择所需的级联关系.否则可能酿成 ...

  7. gdb 不同位置,函数调用参数显示差异

    gdb 不同位置,函数调用参数显示差异,如: copy_strings (argc=1, argv=0xffcf08, page=0xffce6c, p=131068, from_kmem=2) at ...

  8. Educational Codeforces Round 48 (Rated for Div. 2)G. Appropriate Team

    题意:求满足条件的(i,j)对数:\(gcd(v,a_i)=x,lcm(v,a_j)=y\) 题解:\(x|a_i,a_j|y\),\(x|y\),考虑质因子p,假设a_i中p次数为a,x中次数为b, ...

  9. 如何开发mis系统--整理

    1.含义: 所谓MIS(管理信息系统--Management Information System)系统,主要指的是进行日常事务操作的系统.这种系统主要用于管理需要的记录,并对记录数据进行相关处理,将 ...

  10. 使用telnet模拟邮件的收发

    smtp协议是一个简单的邮件传输协议,利用它我们可以将邮件发送给别人,这里将通过telnet这个程序利用smtp协议从网易向gmail发送一封邮件 基本步骤如下: 1.使用telnet连接smtp服务 ...