MyBatis的强大特性之一就是它的动态SQL,它能够根据不一样的条件动态地组成SQL语句进行执行。为此,MyBatis提供了一系列强大的表达式,本章将就此进行学习,主要内容直接参考的是官方文档《
动态 SQL》。
一、if
某些条件我须要时才出现,不须要时就不出现,这种需求经常出如今根据用户输入的条件进行搜索的场景,下面来看官方给出的例子:
<select id="findActiveBlogWithTitleLike" resultType="Blog">
SELECT * FROM BLOG
WHERE state = 'ACTIVE'
<if test="title != null">
AND title LIKE #{title}
</if>
</select>
若是传入了title,那么就会对“title”进行模糊查询返回结果。你甚至能够多条件考虑:
<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
choose / when / otherwise 三种元素结合起来使用,相似于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>
三、where / set / trim
3.1 where
咱们先看下面这个例子:
<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>
看似没有什么毛病,但假如全部的 if 条件都没有符合怎么办?SQL语句会变成这样:SELECT * FROM BLOG
WHERE,这显然是个错误的语句。假设只匹配了第二个 if,那么语句又会变成这样:SELECT * FROM BLOG
WHERE
AND title like ‘someTitle’,这显然也是个错误的语句。
为了解决上面的问题,你可使用 where 元素,就像下面这样:
<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 元素,你没必要专门再写WHERE关键字,它会在至少一个子元素条件知足的状况下插入到SQL语句中,甚至你开头写的是 “AND” 或 “OR”,where 元素也会将它们去掉。
3.2 set
相似于 where 元素,用在 update 语句中的动态解决方案叫作 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>
如上例,set 元素会动态前置 SET 关键字,同时会删掉无关的逗号(好比只有第二个 if 知足条件的时候)
3.3 trim
trim 元素则是一个可以灵活设置的元素,你甚至能够经过 trim 实现和 where 或 set 元素相同的功能。trim 元素有四个属性:
- prefix
- prefixOverride
- suffix
- suffixOverride
prefix 表示 “
在前置添加的内容”,prefixOverride 则表示 “
覆盖掉前置内容并添加prefix的内容”,注意,
这些属性的做用都是当trim标签内有SQL语句内容时才会触发。suffix 同理,不过是针对后置的。
多说无益,来看例子:
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG
<trim prefix="WHERE" prefixOverrides="AND |OR">
<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>
</trim>
</select>
上例中trim的使用结果就是,它等同于 where 元素的效果,即:当有SQL语句出现(如上例有 if 知足),前置内容会添加 “WHERE”,若是遇到前置内容是 “AND ” 或者 “OR” 开头,则先覆盖掉前置内容(也即删掉),再添加 prefix 的内容 “WHERE”。
同理,咱们也能够利用 trim 的 prefix 和 suffixOverride 来实现 set 元素的效果:
<update id="updateAuthorIfNecessary">
update Author
<trim prefix="SET" suffixOverrides=",">
<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>
</trim>
where id=#{id}
</update>
四、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>
其中:
- item - 当前迭代的元素
- index - 当前迭代的次数(若是集合是Map,则index为键)
- open - 开头字符串
- separator - 元素间的分隔符
- close - 结尾字符串
如上最终会造成诸如 “... WHERE ID in ( 10, 12, 23, 35, 99 )” 形式的SQL语句。