动态SQL
动态SQL是MyBatis的强大特性之一。在MyBatis中需要借助OGNL的表达式。
- if
- choose(when,otherwise)
- trim(where set)
- foreach
if
if:判断语句
<select id="findActiveBlogWithTitleLike"
resultType="Blog">
SELECT * FROM BLOG
WHERE state = ‘ACTIVE’
<if test="title != null">
AND title like #{title}
</if>
</select>
当title不为空时,执行后面的查询语句。否则相反。
choose、when、otherwise
当我们不想使用所有的条件,而只想从多个条件选择使用一个。可以使用choose元素,类似Java中的switch语句。
<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
例子:
<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’
这时候我们可以使用where元素,它会将子句开头的 “AND” 或 “OR”除去。
<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>
用于动态更新语句的类似解决方案叫做 set。set 元素可以用于动态包含需要更新的列,忽略其它不更新的列。会动态的在首行插入set,并会删除掉额外的逗号
<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>
我们还可以使用trim自定义:
- trim:自定义字符串的截取规则
- prefix="":前缀,trim标签体中是整个字符串拼串后的结果。prefix给拼串后的整个字符串加一个前缀。
- prefixOverrides="":前缀覆盖,去掉整个字符串前面多余的字符串。
- suffix="":后缀,suffix给拼串后的结果加一个后缀
- suffixOverrides="":后缀覆盖,去掉整个字符串后面多余的字符串。
foreach
动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。比如:
<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>
- collection:指定要遍历的集合:list类型的参数会特殊处理封装在map中,map的key就叫list。
- item:将当前遍历出的元素赋值给指定的变量。
- separator:每个元素之间的分隔符。
- open:遍历出所有结果拼接一个开始的字符。
- close:遍历出的所有结果拼接一个结束的字符。
- index:索引。遍历list的时候index是索引,item就是当前的值;遍历map的时候是index表示的就是map的key,item就是map的值。
- #{变量名}就能取出变量的值也就是当前遍历出的元素
bind
bind 元素允许你在 OGNL 表达式以外创建一个变量,并将其绑定到当前的上下文。比如:
<select id="selectBlogsLike" resultType="Blog">
<bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{pattern}
</select>