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 语句有多么 ...
随机推荐
- Golang的session管理器
对于一些需要对用户进行管理(比如验证操作的权限等)的站点来说,session管理器是必不可少的.下面实现了一个线程安全的简单session管理类.生产环境:golang1.4.2+win7x64gol ...
- js时间戳如何转时间
js时间戳如何转时间 一.总结 一句话总结:Date对象分别获取年now.getFullYear()月now.getMonth()+1日now.getDate()即可 Date对象分别获取年now.g ...
- 如何下载一个物种的全部EST序列 | NCBI | 表达序列标签
EST:表达序列标签,expressed sequence tags . 顾名思义,很好理解,就是表达出来的序列,即从基因组DNA上表达出来的RNA,但是我们没法测序RNA,所以我们最终测的是表达序列 ...
- jquery ----> How to Create a Basic Plugin (翻译)
http://learn.jquery.com/plugins/basic-plugin-creation/ 如何创建一个基本的插件 有时候你想在整个代码中提供一些功能. 例如,也许你想要一个单一的方 ...
- 20171023xlVBA递归统计WORD字数
Dim dFilePath As Object, OneKey Sub main_proc() Dim Wb As Workbook, Sht As Worksheet, Rng As Range S ...
- use . adb . get wifi
adb shell 连接手机获取root权限,如果返回的字符串中不包含root字样,再输入su命令回车 继续输入cat /data/misc/wifi/*.conf命令,将会把文件打印出来 ssid表 ...
- Android测试(二)——drozer使用
drozer启动: 1)首先在模拟 器或者安卓设备上开启drozer; 2)然后打开adb,转发端口: adb forward tcp:31415 tcp:31415 3)在电脑上开启drozer: ...
- Python-Selenium中chromeDriver限制图片和Javascript加载
我们有的时候使用Selenium会希望能够限制图片和Javascript执行,从而提高网页加载速度. options=webdriver.ChromeOptions() prefs={ 'p ...
- 第二阶段——个人工作总结DAY06
1.昨天做了什么:昨天做完了修改密码的界面.(有点丑) 2.今天打算做什么:今天制作时间轴. 3.遇到的困难:无.
- Apache commons(Java常用工具包)简介
Apache Commons是一个非常有用的工具包,解决各种实际的通用问题,下面是一个简述表,详细信息访问http://jakarta.apache.org/commons/index.html Be ...