最近在学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. Unity --- 纹理压缩基本知识点

    1.Unity支持的压缩格式的分类,这里主要指Android平台和IOS平台: DXT格式 --- Nvidia Tegra(图睿)提供ETC  --- 安卓原生支持的,OPNEGL2.0都支持,ET ...

  2. android-------Java 常问的基础面试题

      1."=="和equals方法究竟有什么区别? ==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个 ...

  3. android-------Android Studio使用MAT分析工具遇到的错误

    今天主要介绍一下我使用MAT工具分析文件时遇到的一个错误 Error opening heap dump 'a.hprof'. Check the error log for further deta ...

  4. 02linux 基本命令

    系统环境变量的设置 以nginx为例: 方式一: ~/.bash_profile  这是个人的 /etc/profile 为系统的环境变量 vim /etc/profile.d/nginx.sh #在 ...

  5. 【洛谷p1012】拼数

    (今天yuezhuren大课间放我们出来了……) (另外今天回了两趟初中部) 拼数[传送门] 洛谷算法标签: (然鹅这两个学的都不好,能过真的how strange) 开始的时候没读题啊,直接暴力so ...

  6. 『TensorFlow』SSD源码学习_其一:论文及开源项目文档介绍

    一.论文介绍 读论文系列:Object Detection ECCV2016 SSD 一句话概括:SSD就是关于类别的多尺度RPN网络 基本思路: 基础网络后接多层feature map 多层feat ...

  7. ORACLE中ESCAPE关键字用法

    ESCAPE用法 1.使用 ESCAPE 关键字定义转义符: 在模式中,当转义符置于通配符之前时,该通配符就解释为普通字符. 2.ESCAPE 'escape_character'  允许在字符串中搜 ...

  8. 【Python】Anaconda配置

    Anaconda 是一个用于科学计算的Python发行版,支持 Linux.Mac.Windows 系统,提供了包管理与环境管理的功能,可以很方便地解决多版本 Python 并存.切换以及各种第三方包 ...

  9. Humble Numbers HDU - 1058 2分dp

    JGShining's kingdom consists of 2n(n is no more than 500,000) small cities which are located in two ...

  10. 连接zookeeper+solr的服务器超时

    在连接zookeeper+solr的服务器超时,如果检查各ip地址都没有变动,各部分工程也没有书写问题,那么连接超时,就可能是该服务器内存分配过少,性能不足的问题,扩大该服务器内存即可.