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語句。