mybatis動態sql總結

前言

平時在開發中,針對動態sql這塊目前是薄弱點,本身根據官網在對應項目邊測試邊寫博客,此篇只是爲了加深動態sql的熟練度,有不到之處敬請批評指正!sql

1.if

使用動態 SQL 最多見情景是根據條件包含 where 子句的一部分。好比:數組

<select id="findActiveBlogWithTitleLike"
     resultType="Blog">
  SELECT * FROM BLOG
  WHERE state = ‘ACTIVE’
  <if test="title != null">
    AND title like #{title}
  </if>
</select>

這條語句提供了可選的查找文本功能。若是不傳入 「title」,那麼全部處於 「ACTIVE」 狀態的 BLOG 都會返回;若是傳入了 「title」 參數,那麼就會對 「title」
一列進行模糊查找並返回對應的 BLOG 結果(細心的讀者可能會發現,「title」 的參數值須要包含查找掩碼或通配符字符)。
若是但願經過 「title」 和 「author」 兩個參數進行可選搜索該怎麼辦呢?首先,我想先將語句名稱修改爲改名副其實的名稱;接下來,只須要加入另外一個條件便可。dom

<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>

2. choose、when、otherwise

有時候,咱們不想使用全部的條件,而只是想從多個條件中選擇一個使用。針對這種狀況,MyBatis 提供了 choose 元素,它有點像 Java 中的 switch 語句。
仍是上面的例子,可是策略變爲:傳入了 「title」 就按 「title」 查找,傳入了 「author」 就按 「author」 查找的情形。若二者都沒有傳入,
就返回標記爲 featured 的 BLOG(這多是管理員認爲,與其返回大量的無心義隨機 Blog,還不如返回一些由管理員精選的 Blog)。ide

<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>

3. trim、where、set

前面幾個例子已經方便地解決了一個臭名昭著的動態 SQL 問題。如今回到以前的 「if」 示例,此次咱們將 「state = ‘ACTIVE’」 設置成動態條件,看看會發生什麼。測試

<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 會變成這樣:code

SELECT * FROM BLOG
WHERE

這會致使查詢失敗。若是匹配的只是第二個條件又會怎樣?這條 SQL 會是這樣:對象

SELECT * FROM BLOG
WHERE
AND title like ‘someTitle’

這個查詢也會失敗。這個問題不能簡單地用條件元素來解決。這個問題是如此的難以解決,以致於解決過的人不會再想碰到這種問題。
MyBatis 有一個簡單且適合大多數場景的解決辦法。而在其餘場景中,能夠對其進行自定義以符合需求。而這,只須要一處簡單的改動:blog

<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」 子句。並且,若子句的開頭爲 「AND」 或 「OR」,where 元素也會將它們去除。
若是 where 元素與你指望的不太同樣,你也能夠經過自定義 trim 元素來定製 where 元素的功能。好比,和 where 元素等價的自定義 trim 元素爲:索引

<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>

prefixOverrides 屬性會忽略經過管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子會移除全部 prefixOverrides 屬性中指定的內容,而且插入 prefix 屬性中指定的內容。
用於動態更新語句的相似解決方案叫作 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>

這個例子中,set 元素會動態地在行首插入 SET 關鍵字,並會刪掉額外的逗號(這些逗號是在使用條件語句給列賦值時引入的)。
來看看與 set 元素等價的自定義 trim 元素吧:

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

注意,咱們覆蓋了後綴值設置,而且自定義了前綴值。

4. 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>

foreach 元素的功能很是強大,它容許你指定一個集合,聲明能夠在元素體內使用的集合項(item)和索引(index)變量。它也容許你指定開頭與結尾的字符串以及集合項迭代之間的分隔符。 這個元素也不會錯誤地添加多餘的分隔符,看它多智能! 提示 你能夠將任何可迭代對象(如 List、Set 等)、Map 對象或者數組對象做爲集合參數傳遞給 foreach。當使用可迭代對象或者數組時,index 是當前迭代的序號, item 的值是本次迭代獲取到的元素。當使用 Map 對象(或者 Map.Entry 對象的集合)時,index 是鍵,item 是值。 至此,咱們已經完成了與 XML 配置及映射文件相關的討論。下一章將詳細探討 Java API,以便你能充分利用已經建立的映射配置。

相關文章
相關標籤/搜索