最近在学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. 关于前端SEO的一些常用知识总结

    Search English Optimization,搜索引擎优化,简称为SEO. (1)网站结构布局优化:尽量简单 1. 控制首页链接数量:首页链接不能太多,一旦太多,没有实质性的链接,很容易影响 ...

  2. Codeforces 934D - A Determined Cleanup

    934D - A Determined Cleanup 思路: 找规律,和k进制的求法差不多,答案的奇数位是p%k,偶数位如果p%k!=0,那么答案是k-p%k,否则为0. 代码: #include& ...

  3. RNA Spike-in Control(转)

    Spike-in Control:添加/加入(某种物质)的对照(组)在某些情况下,待检验样本中不含待测物质或者含有但是浓度很低,为了证明自己建立的方法能对样本中待测物质进行有效的检测,可在待检样本中加 ...

  4. CSS3实现烟花特效 --web前端

    烟花特效,比较简单,直接贴代码了…… <!DOCTYPE html><html lang="en"><head> <meta charse ...

  5. 4步win7下简单FTP服务器搭建(试验成功)

    本文介绍通过win7自带的IIS来搭建一个只能实现基本功能的FTP服务器,第一次装好WIN7后我愣是没整出来,后来查了一下网上资料经过试验后搭建成功,其实原理和步骤与windows前期的版本差不多,主 ...

  6. H3C S6800交换机 BCM shell命令

    H3C S6800交换机 BCM shell命令 http://wgli978.blog.163.com/blog/static/13592877220172315858831/ <H3C> ...

  7. android -------- ConstraintLayout Guideline和Barrier(四)

    前面的文章 ConstraintLayout 介绍 (一) ConstraintLayout约束属性 (二) ConstraintLayout 宽高比和偏移量比(三) 此博文主要讲解:Guidelin ...

  8. ActiveMQ的学习整理(代码实现PTP,以及Pub/Sub)

    (一)由于在实习过程中需要用到ActiveMQ,在网上看了很多文章,现在整理出来以防忘记. (二)这篇文章比较适合之前没有接触过的同学,在看下面文章的过程中,建议先学习参考链接中的知识点,然后自己再参 ...

  9. vue嵌套路由--params传递参数

    在嵌套路由中,父路由向子路由传值除了query外,还有params,params传值有两种情况,一种是值在url中显示,另一种是值不显示在url中. 1.显示在url中index.html <d ...

  10. 【LeetCode】Valid Parentheses合法括号

    给定一个仅包含 '('.')'.'{'.'}'.'['.']'的字符串,确定输入的字符串是否合法. e.g. "()"."()[]{}"."[()]( ...