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
1.if标记。
动态 SQL 通常要做的事情是有条件地包含 where 子句的一部分。常用形式:
1 <select id="**" resultType="**" parameterType="**"> 2 select * from table where 1=1 3 <if test="attr!=null"> 4 and attrColumn>#{attr} 5 </if> 6 </select>
这条语句提供了一个可选的文本查找类型的功能。在where后面加上1=1,是为了与后面的and连接,否则会出现语法错误(不过利用后面的where标记便不再需要),若attr属性不为null,执行语句为:
1 select * from table where 1=1 and attrColumn>?
if是动态sql中最最常用的标记
2.choose, when, otherwise标记。
有些时候,我们不想用到所有的条件语句,而只想从中择其一二。针对这种情况,MyBatis 提供了 choose 元素。常用形式:
1 select * from table where 1=1 2 <choose> 3 <when test="attr1!=null"> 4 and attrColumn like #{attr} 5 </when> 6 …… 7 <otherwise> 8 and attr2 is not null 9 </otherwise> 10 </choose>
choose标记类似于java或者C语言中的switch-case语句的作用,至上而下执行,满足when语句则执行后面相应语句,否则跳到下一条执行语句。若数据库中attr1属性不为null,则执行语句为:
1 select * from table where 1=1 and attrColumn like ?
若为null,则执行语句为:
1 select * from table where 1=1 and attr2 is not null
3.where标记。
常用形式:
1 select * from table 2 <where> 3 <if test="attr1!=null"> 4 attr1Column like #{attr1} 5 </if> 6 <if test="attr2!=null"> 7 and attr2Column =#{attr2} 8 </if> 9 </where>
可以看到,使用where标记有两个好处:1. 不再需要在where后面加上1=1这个条件;2.会智能处理and,若attr1,attr2不为null,执行语句为:
1 select * from table where attr1Column like ? and attr2Column =?
若attr1为null,attr2不为null,则执行语句为:
1 select * from table where attr2Column = ?
这个时候where标记的智能就体现出来了:where 元素知道只有在一个以上的if条件有值的情况下才去插入“WHERE”子句。而且,若最后的内容是“AND”或“OR”开头的,where 元素也知道如何将他们去除。
4.set标记。
set 元素会动态前置 SET 关键字,同时也会消除无关的逗号,因为用了条件语句之后很可能就会在生成的赋值语句的后面留下这些逗号。常用形式:
1 update table 2 <set> 3 <if test="attr1!= null">attr1Column=#{attr1},</if> 4 <if test="attr2!= null">attr2Column=#{attr2},</if> 5 </set> 6 where attr3Column=#{attr3}
显然,set标记主要用于更新数据表,使用set标记是一种智能的赋值,智能处理后面的“,”,若attr1,attr2不为null,执行语句为:
1 update table set attr1Column=?,attr2Column=? where attr3Column = ?
可以看到最后一个if判断的“,”已经被智能去掉。
5.trim标记。
trim标记一般可以与where,set标记组合使用。
trim标记的核心是4个元素,
prefix | suffix | prefixOverrides | suffixOverrides |
---|---|---|---|
前缀 | 后缀 | 自动判断前置 | 自动判断后置 |
利用trim代理set:
1 <trim prefix="SET" suffix="WHERE attr2Column = #{attr2}" suffixOverrides=","> 2 <if test="attr1 != null and attr1 != '' "> attr1Column = #{attr1}, 3 </if> 4 …… 5 </trim>
等同于:
1 <set> 2 <if test="attr1!= null and attr1!=''">attr1Column=#{attr1}, 3 </if> 4 …… 5 </set> 6 where attr2Column=#{attr2}
利用trim代理where标记:
1 select * from table 2 <trim prefix="where" prefixOverrides="and|or"> 3 <if test="attr1!=null"> 4 and attr1Column like #{attr1} 5 </if> 6 <if test="attr2!=null"> 7 and attr2Column =#{attr2} 8 </if> 9 </trim>
等同于:
1 select * from table 2 <where> 3 <if test="attr1!=null"> 4 attr1Column like #{attr1} 5 </if> 6 <if test="attr2!=null"> 7 and attr2Column =#{attr2} 8 </if> 9 </where>
6.foreach标记。
foreach标记是最为强大的一个标记,最基本的功能是用来实现对一个集合进行遍历查询,循环赋值。通常是在构建 IN 条件语句的时候使用。
foreach标记主要是使用一下一些属性标记来实现:
item:迭代的内容
collection:循环的集合或指定的类型
separator:元素之间的分隔符
open:开始符,可选属性
close:闭合符,可选属性,一般与open联合使用
index:list的序号,可选属性
使用foreach进行遍历查询的常用形式:
1 select * from table 2 <where> 3 id in 4 <foreach item="item" index="index" collection="list" 5 open="(" separator="," close=")"> 6 #{item} 7 </foreach> 8 </where>
该语句的意思便是对list进行遍历,每个元素的分隔符为”,”,list中为程序中赋的id的初始值,通过该语句查询指定的id
使用foreach进行循环赋值的常用形式:
insert into table(attr1, attr2) values <foreach item="item" collection="list" separator="," > (#{item.attr1}, #{item.attr2}) </foreach>
以上便是mybaits框中常用到几个动态标记