Mybatis之trim标签的理解
最近在学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标签的理解的更多相关文章
- Mybatis中trim标签的用法
select * from t_user <trim prefix="WHERE" prefixOverrides="and"> <if te ...
- mybatis : trim标签, “等于==”经验, CDATA标签 ,模糊查询CONCAT,LIKE
一.My Batis trim标签有点类似于replace效果. trim 属性, prefix:前缀覆盖并增加其内容 suffix:后缀覆盖并增加其内容 prefixOverrides:前缀判断的条 ...
- MyBatis动态SQL中trim标签的使用
My Batis 官方文档 对 动态SQL中使用trim标签的场景及效果介绍比较少. 事实上trim标签有点类似于replace效果. trim 属性 prefix:前缀覆盖并增加其内容 suffix ...
- mybatis动态插入数据(使用trim标签)
知识点: 当向一张表里插入数据,传入的参数不固定时,使用到mybatis的动态插入(trim标签) 参考博客:https://blog.csdn.net/h12kjgj/article/details ...
- Mybatis学习笔记11 - 动态sql之trim标签
trim标签体中是整个字符串拼串后的结果.prefix="" 前缀: prefix给拼串后的整个字符串加一个前缀prefixOverrides="" 前缀覆盖: ...
- Mybatis中的ognl表达式。及myabtis where标签/if test标签/trim标签
1.mybatis默认支持使用ognl表达式来生成动态sql语句 MyBatis中可以使用OGNL的地方有两处: 动态SQL表达式中 ${param}参数中 上面这两处地方在MyBatis中处理的时候 ...
- MyBatis where、set、trim标签的用法
<!-- 4.3.1 where用法 <where>标签的作用:如果该便签包含的元素中有返回值,就插入一个where:如果 where后面的字符串是一and或or开头的,就将它们剔除 ...
- MyBatis动态添加—trim标签
做添加时,部分字段有值,没值的字段不添加,这就是动态添加,使用 trim 标签就可以实现. <insert id="insertSysUser" parameterType= ...
- 9.mybatis动态SQL标签的用法
mybatis动态SQL标签的用法 动态 SQL MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么 ...
随机推荐
- node+ts的心得与坑
首先先明确,用node+ts的目的,为什么不ng+ts.这一点后面还会反复提醒自己 node毕竟不是ng. 用node的理由: 处理js,在后端操纵dom,读写类html格式的东西,比直接用py的后端 ...
- MySQL学习(八)
连接查询 1 集合的特点:无序性,唯一性 集合的运算:求并集,求交集,求笛卡尔积 表和集合的关系 一张表就是一个集合,每一行就是一个元素 疑问:集合不能重复,但我有可能两行数据完全一样 答:mysql ...
- POJ 3076 Sudoku
3076 思路: dfs + 剪枝 首先,如果这个位置只能填一种字母,那就直接填 其次,如果对于每一种字母,如果某一列或者某一行或者某一块只能填它,那就填它 然后,对于某个位置如果不能填字母了,或者某 ...
- SPOJ 刷题记录
按点赞数降序 297 二分 #include<bits/stdc++.h> using namespace std; #define fi first #define se second ...
- VMware vSphere client 中英文语言界面设置
安装的时候可以选择简体中文,然后安装后,对vsphere client的执行程序制作快捷方式 以win7 x64环境默认路径为例 英文启动如下: "C:Program Files (x86) ...
- English trip V1 - 19.Where Am I? 我在哪里?Teacher:Patrick Key:Ask for and directions
In this lesson you will learn to ask for and give directions. 本节课你将学习到学会问路和指路. 课上内容(Lesson) 人类的几种感: ...
- Winform开发框架之框架演化
Winform开发框架方面的文章我介绍很多了,有宏观介绍,也有部分技术细节的交流,每次我希望能从不同角度,不同方面来介绍我的WInform开发框架,这些其实都是来源于客户的需求,真实的项目场景.本文主 ...
- xsd与xml和类(class)对象之间的互相转换
xsd与xml和类(class)对象之间的互相转换 . 第一:通过现有的已经写好的xsd来生成class(.cs)文件. 在您Visual Studio的安装目录下的SDKv2.0Bin中有个应用程序 ...
- Spring Cloud之注册中心搭建
一.注册中心服务端搭建 1)引入相关Maven坐标 <dependency> <groupId>org.springframework.cloud</groupId> ...
- java.lang.IllegalArgumentException: Service Intent must be explicit 解决办法
java.lang.IllegalArgumentException: Service Intent must be explicit 意思是服务必须得显式的调用 我之前是这样使用绑定Service的 ...