目录
动态 SQL
MyBatis强大特性之一便是动态SQL。如果有使用JDBC或其他类似框架的经验,就能体会到根据不同条件拼接SQL语句有多么痛苦。拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号。利用动态SQL这一特性可以彻底摆脱这种痛苦
通常使用动态SQL不可能是独立的一部分,MyBatis当然使用一种强大的动态SQL语言来改进这种情形,这种语言可以被用在任意的SQL映射语句中
动态SQL元素和使用JSTL或其他类似基于XML的文本处理器相似。在MyBatis之前的版本中,有很多的元素需要来了解。MyBatis 3大大提升了它们,现在用不到原先一半的元素就可以了。MyBatis采用功能强大的基于OGNL的表达式来消除其他元素
可以在XML映射文件内,以XML标签的形式编写动态SQL,完成逻辑判断和动态拼接SQL的功能
所有语法中的条件参数,如果没有传入则跳过,不影响SQL语句的执行
Mybatis提供了9种动态SQL标签:<if />、<choose />、<when />、<otherwise />、<trim />、<where />、<set />、<foreach />、<bind />都是<sql>元素的子元素。
<!-- 使用方式一 -->
<select id="">
<if test=""></if>
<choose>
<when test=""></when>
<otherwise></otherwise>
</choose>
</select>
<!-- 使用方式二 -->
<sql id="idsql"></sql>
<select id="">
<include refid="idsql"></include>
</select>
执行原理:使用OGNL表达式,从SQL参数对象中计算表达式的值,根据表达式的值动态拼接SQL,以此来完成动态SQL的功能。
if
基本语法:
<if test="">
</if>
test:判断条件,双条件用and连接, 当中可插入其他语句
choose (when, otherwise)
它有点像Java中的switch语句
基本语法:
<choose>
<when test=""></when>
<when test=""></when>
<otherwise></otherwise>
</choose>
trim (where, set)
属性 | 描述 |
---|---|
prefix | 表示在trim标签包裹的部分的前面添加内容(注意:是没有prefixOverrides,suffixOverrides的情况下),如果有表示覆盖 |
suffix | 表示在trim标签包裹的部分的后面添加内容(注意:是没有prefixOverrides,suffixOverrides的情况下),如果有表示覆盖 |
prefixOverrides | 表示在trim标签包裹的部分删除前面的(自己包含的) |
suffixOverrides | 表示在trim标签包裹的部分删除后面的 |
where
where元素能在只有在一个以上的if条件有值的情况下才去插入"WHERE"子句。而且,若最后的内容是"and"或"or"开头的,where元素也知道如何将他们去除
<where>
select * from student
<if test="title!=null">
AND title like #{title}
</if>
<if test=""></if>
<if test=""></if>
</where>
执行情况:
title==null:select * from student
title!=null:select * from student where title like #{title}
trim实现where
如果where元素没有按正常套路出牌,可以通过自定义trim元素来定制想要的功能
<trim prefix="WHERE" prefixOverrides="AND | OR" suffix="" suffixOverrides="">
</trim>
prefixOverrides属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)它带来的结果就是所有在prefixOverrides属性中指定的内容将被移除,并且插入prefix属性中指定的内容。
set
用于动态更新语句的解决方案叫做set。set元素可以被用于动态包含需要更新的列,而舍去其他的
<update id="">
update student
<set>
<if test="username!=null">username = #{username},</if>
<if test=""></if>
</set>
</update>
set 元素会动态前置 SET 关键字,同时也会消除无关的逗号,因为用了条件语句之后很可能就会在生成的赋值语句的后面留下这些逗号
trim实现set
<trim prefix="SET" prefixOverrides="" suffix="" suffixOverrides=",">
</trim>
foreach
动态SQL的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建IN条件语句的时候
foreach一共有三种类型,分别为List、Array、Map三种
<select id="">
select * from student where username in
<foreach collection="list" item="item" index="index" open="(" close=")" separator=",">
#{item}
</foreach>
</select>
(1)允许指定一个集合,声明可以用在元素体内的集合项和索引变量
(2)允许指定开闭匹配的字符串以及在迭代中间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符
注意:可以将一个List实例或者数组作为参数对象传给MyBatis,当这么做的时候,MyBatis会自动将它包装在一个Map中并以名称为键。List实例将会以"list"作为键,而数组实例的键将是"array"
属性 | 描述 |
---|---|
item | 循环体中的具体对象(每次循环出来的对象)。支持属性的点路径访问,如item.age,item.info.details。具体说明:在list和数组中是其中的对象,在map中是value。必选 |
collection | 要做foreach的对象,作为入参时,List<?>对象默认用list代替作为键,数组对象有array代替作为键,Map对象用map代替作为键。 当然在作为入参时可以使用@Param(“keyName”)来设置键,设置keyName后,list,array,map将会失效。 除了入参这种情况外,还有一种作为参数对象的某个字段的时候。举个例子: 如果User有属性List ids。入参是User对象,那么这个collection = “ids” 如果User有属性Ids ids;其中Ids是个对象,Ids有个属性List id;入参是User对象,那么collection = “ids.id” 上面只是举例,具体collection等于什么,就看你想对那个元素做循环。 该参数为必选。 |
separator | 元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。 |
open | foreach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。该参数可选。 |
close | foreach代码的关闭符号,一般是)和open="("合用。常用在in(),values()时。该参数可选。 |
index | 在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选。 |
bind
bind元素可以从OGNL表达式中创建一个变量并将其绑定到上下文
动态 SQL 中可插拔的脚本语言
MyBatis 从 3.2 开始支持可插拔的脚本语言,因此你可以在插入一种语言的驱动(language driver)之后来写基于这种语言的动态 SQL 查询。