9.mybatis动态SQL标签的用法
mybatis动态SQL标签的用法
动态 SQL
MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦。拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意的 SQL 映射语句中。
动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多的元素需要来了解。MyBatis 3 大大提升了它们,现在用不到原先一半的元素就可以了。MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
if
动态 SQL 通常要做的事情是有条件地包含 where 子句的一部分。比如:
2
3
4
5
6
7
8
9
|
<select id= "findActiveBlogWithTitleLike"
resultType= "Blog" >
SELECT * FROM BLOG
WHERE state = ‘ACTIVE’
< if test= "title != null" >
AND title like #{title}
</ if >
</select>
|
这条语句提供了一个可选的文本查找类型的功能。如果没有传入“title”,那么所有处于“ACTIVE”状态的BLOG都会返回;反之若传入了“title”,那么就会把模糊查找“title”内容的BLOG结果返回(就这个例子而言,细心的读者会发现其中的参数值是可以包含一些掩码或通配符的)。
如果想可选地通过“title”和“author”两个条件搜索该怎么办呢?首先,改变语句的名称让它更具实际意义;然后只要加入另一个条件即可。
2
3
4
5
6
7
8
9
10
11
|
<select id= "findActiveBlogLike"
resultType= "Blog" >
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
< if test= "title != null" >
AND title like #{title}
</ if >
< if test= "author != null and author.name != null" >
AND author_name like #{author.name}
</ if >
</select>
|
choose, when, otherwise
有些时候,我们不想用到所有的条件语句,而只想从中择其一二。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
还是上面的例子,但是这次变为提供了“title”就按“title”查找,提供了“author”就按“author”查找,若两者都没有提供,就返回所有符合条件的BLOG(实际情况可能是由管理员按一定策略选出BLOG列表,而不是返回大量无意义的随机结果)。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<select id= "findActiveBlogLike"
resultType= "Blog" >
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<when test= "title != null" >
AND title like #{title}
</when>
<when test= "author != null and author.name != null" >
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
|
trim, where, set
前面几个例子已经合宜地解决了一个臭名昭著的动态 SQL 问题。现在考虑回到“if”示例,这次我们将“ACTIVE = 1”也设置成动态的条件,看看会发生什么。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<select id= "findActiveBlogLike"
resultType= "Blog" >
SELECT * FROM BLOG
WHERE
< if test= "state != null" >
state = #{state}
</ if >
< if test= "title != null" >
AND title like #{title}
</ if >
< if test= "author != null and author.name != null" >
AND author_name like #{author.name}
</ if >
</select>
|
如果这些条件没有一个能匹配上将会怎样?最终这条 SQL 会变成这样:
SELECT * FROM BLOG WHERE
这会导致查询失败。如果仅仅第二个条件匹配又会怎样?这条 SQL 最终会是这样:
SELECT * FROM BLOG WHERE AND title like ‘someTitle’
这个查询也会失败。这个问题不能简单的用条件句式来解决,如果你也曾经被迫这样写过,那么你很可能从此以后都不想再这样去写了。
MyBatis 有一个简单的处理,这在90%的情况下都会有用。而在不能使用的地方,你可以自定义处理方式来令其正常工作。一处简单的修改就能得到想要的效果:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<select id= "findActiveBlogLike"
resultType= "Blog" >
SELECT * FROM BLOG
<where>
< if test= "state != null" >
state = #{state}
</ if >
< if test= "title != null" >
AND title like #{title}
</ if >
< if test= "author != null and author.name != null" >
AND author_name like #{author.name}
</ if >
</where>
</select>
|
where 元素知道只有在一个以上的if条件有值的情况下才去插入“WHERE”子句。而且,若最后的内容是“AND”或“OR”开头的,where 元素也知道如何将他们去除。
如果 where 元素没有按正常套路出牌,我们还是可以通过自定义 trim 元素来定制我们想要的功能。比如,和 where 元素等价的自定义 trim 元素为:
<trim prefix="WHERE" prefixOverrides="AND |OR ">... </trim>
prefixOverrides 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)。它带来的结果就是所有在 prefixOverrides 属性中指定的内容将被移除,并且插入 prefix 属性中指定的内容。
类似的用于动态更新语句的解决方案叫做 set。set 元素可以被用于动态包含需要更新的列,而舍去其他的。比如:
2
3
4
5
6
7
8
9
10
11
|
<update id= "updateAuthorIfNecessary" >
update Author
<set>
< if test= "username != null" >username=#{username},</ if >
< if test= "password != null" >password=#{password},</ if >
< if test= "email != null" >email=#{email},</ if >
< if test= "bio != null" >bio=#{bio}</ if >
</set>
where id=#{id}
</update>
|
这里,set 元素会动态前置 SET 关键字,同时也会消除无关的逗号,因为用了条件语句之后很可能就会在生成的赋值语句的后面留下这些逗号。
若你对等价的自定义 trim 元素的样子感兴趣,那这就应该是它的真面目:
2
3
4
|
<trim prefix= "SET" suffixOverrides= "," >
...
</trim>
|
注意这里我们忽略的是后缀中的值,而又一次附加了前缀中的值。
foreach
动态 SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候。比如:
2
3
4
5
6
7
8
9
10
|
<select id= "selectPostIn" resultType= "domain.blog.Post" >
SELECT *
FROM POST P
WHERE ID in
<foreach item= "item" index= "index" collection= "list"
open= "(" separator= "," close= ")" >
#{item}
</foreach>
</select>
|
foreach 元素的功能是非常强大的,它允许你指定一个集合,声明可以用在元素体内的集合项和索引变量。它也允许你指定开闭匹配的字符串以及在迭代中间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。
注意 你可以将任何可迭代对象(如列表、集合等)和任何的字典或者数组对象传递给foreach作为集合参数。当使用可迭代对象或者数组时,index是当前迭代的次数,item的值是本次迭代获取的元素。当使用字典(或者Map.Entry对象的集合)时,index是键,item是值。
到此我们已经完成了涉及 XML 配置文件和 XML 映射文件的讨论。下一部分将详细探讨 Java API,这样才能从已创建的映射中获取最大利益。
bind
bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。比如:
<select id="selectBlogsLike" resultType="Blog"><bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />SELECT * FROM BLOGWHERE title LIKE #{pattern} </select>
Multi-db vendor support
一个配置了“_databaseId”变量的 databaseIdProvider 对于动态代码来说是可用的,这样就可以根据不同的数据库厂商构建特定的语句。比如下面的例子:
2
3
4
5
6
7
8
9
10
11
12
|
<insert id= "insert" >
<selectKey keyProperty= "id" resultType= "int" order= "BEFORE" >
< if test= "_databaseId == 'oracle'" >
select seq_users.nextval from dual
</ if >
< if test= "_databaseId == 'db2'" >
select nextval for seq_users from sysibm.sysdummy1"
</ if >
</selectKey>
insert into users values (#{id}, #{name})
</insert>
|
动态 SQL 中可插拔的脚本语言
MyBatis 从 3.2 开始支持可插拔的脚本语言,因此你可以在插入一种语言的驱动(language driver)之后来写基于这种语言的动态 SQL 查询。
可以通过实现下面接口的方式来插入一种语言:
2
3
4
5
6
|
public interface LanguageDriver {
ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql);
SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType);
SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType);
}
|
一旦有了自定义的语言驱动,你就可以在 mybatis-config.xml 文件中将它设置为默认语言:
2
3
4
5
6
7
|
<typeAliases>
<typeAlias type= "org.sample.MyLanguageDriver" alias= "myLanguage" />
</typeAliases>
<settings>
<setting name= "defaultScriptingLanguage" value= "myLanguage" />
</settings>
|
除了设置默认语言,你也可以针对特殊的语句指定特定语言,这可以通过如下的 lang 属性来完成:
<select id="selectBlog" lang="myLanguage">SELECT * FROM BLOG </select>
或者在你正在使用的映射中加上注解 @Lang 来完成:
2
3
4
5
6
|
public interface Mapper {
@Lang (MyLanguageDriver. class )
@Select ( "SELECT * FROM BLOG" )
List<Blog> selectBlog();
}
|
注意 可以将 Apache Velocity 作为动态语言来使用,更多细节请参考 MyBatis-Velocity 项目。
转载于:https://www.cnblogs.com/holly8/p/6026295.html
9.mybatis动态SQL标签的用法相关推荐
- Mybatis动态sql标签说明
一.简述 1️⃣config 文件常用标签 properties 标签:引入外部 properties 文件资源. settings 标签:设置 mybatis 全局行为. typeAlias 标签: ...
- mybatis动态sql标签的使用
动态 SQL MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦.拼接的时候要确保不能忘了必要的空格 ...
- MyBatis动态sql之foreach用法
目录 1.foreach元素的属性 2.collection属性值的三种情况 3.代码示例 3.1 collection属性值为List(Array等同): 3.2 collection属性值类型为M ...
- Mybatis系列全解(八):Mybatis的9大动态SQL标签你知道几个?提前致女神!
封面:洛小汐 作者:潘潘 2021年,仰望天空,脚踏实地. 这算是春节后首篇 Mybatis 文了~ 跨了个年感觉写了有半个世纪 - 借着女神节 ヾ(◍°∇°◍)ノ゙ 提前祝男神女神们越靓越富越嗨森! ...
- MyBatis——动态SQL语句——if标签和where标签复合使用
功能需求 根据性别和名字查询用户 官方文档 MyBatis--动态 SQL SQL语句 SELECT id, username, birthday, sex, address FROM `user` ...
- Mybatis 动态sql语句(if标签和where标签)
功能:根据性别和名字查询用户 查询sql语句: SELECT id, username, birthday, sex, address FROM `user` WHERE sex = 1 AND us ...
- 面试题—Mybatis动态sql是什么意思?常用的标签有哪些和用途?
传统jdbc方法中,在写组合的多表复杂sql语句时,需要去拼接sql语句,稍不注意少写一个空格或"",就会导致报错. 这个Mybatis动态sql的功能,就拥有有效的解决了这个问题 ...
- Mybatis中XML的文件SQL语句与动态sql标签(trim|where|set|foreach|if|choose|when|otherwise|bind)
在xml中写sql语句有很多的规范.标准,有时候想要找对应的例子还得翻一翻以前的代码,这里干脆对遇到的情况做个记录. 一,新建XML文件 <?xml version="1.0" ...
- mybatis动态sql及分页
1. 动态sql简述 mybatis的动态sql语句是基于OGNL表达式的.可以方便的在sql语句中实现某些逻辑. 总体说来mybatis动态SQL语句主要有以下几类: if 语句 (简单的条件判断) ...
最新文章
- go 连接 kafka 写 mysql
- NET中的异步编程(二)- 传统的异步编程
- Git 技术篇 - git remote修改、移除仓库源的使用方法,git添加仓库源提示fatal: remote origin already exists.问题解决
- go语言中使用递归函数实现文件目录的遍历
- java B2B2C源码电子商务平台 -SpringCloud配置中心高可用搭建
- 马斯克:将打造一款2.5万美元电动汽车
- TCP 半连接队列和全连接队列满了,怎么破?
- 学习 nltk —— TF-IDF
- 项目经理要提升需求分析的能力
- Silverlight Quick Starts翻译(二):第一章 创建一个Silverlight工程
- 已知直角三角形的周长,求可以构成三角形的情况
- 0 基础 Java 自学之路(2021年最新版)
- STM32学习心得二十五:光敏传感器原理及实验
- 流行前端几大UI框架排行榜
- 7-3 约分最简分式
- slim 搭建rnn_RNN入门(三)利用LSTM生成旅游点评
- 在MINIX3中实现Earliest-Deadline-First近似实时调度功能
- 上手评测:华为nova8和nova7Pro哪个好?区别是什么
- Win10开始菜单打不开
- 如何实现水泥窑分散点信号集中控制?
热门文章
- ADO.NET 连接Access2007和Access2003
- android LaunchMode之SingleTask
- s7-200与计算机modbus通讯案例,西门子200MODBUS通讯案例.doc
- 隐藏画质代码_如何让千元机高画质满帧吃鸡?最全教程奉上!
- Aurora 8B/10B、PCIe 2.0、SRIO 2.0三种协议比较
- 魅蓝5s的android系统版本,魅族魅蓝5S的手机系统是什么
- 各种pytorch项目
- pytorch定义神经卷积网络CNN源码
- 重磅发布: 阿里云WAF日志实时分析上线 (含视频)
- spring框架使用Quartz执行定时任务实例详解