MyBatis 3 動態(tài)SQL-trim、where、set

2022-04-11 10:30 更新

trim、where、set

前面幾個例子已經(jīng)方便地解決了一個臭名昭著的動態(tài) SQL 問題?,F(xiàn)在回到之前的 “?if?” 示例,這次我們將 “?state = ‘ACTIVE’?” 設(shè)置成動態(tài)條件,看看會發(fā)生什么。

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

這個查詢也會失敗。這個問題不能簡單地用條件元素來解決。這個問題是如此的難以解決,以至于解決過的人不會再想碰到這種問題。

MyBatis 有一個簡單且適合大多數(shù)場景的解決辦法。而在其他場景中,可以對其進行自定義以符合需求。而這,只需要一處簡單的改動:

<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 ?元素只會在子元素返回任何內(nèi)容的情況下才插入 “?WHERE?” 子句。而且,若子句的開頭為 “?AND?” 或 “?OR?”,?where ?元素也會將它們?nèi)コ?

如果 ?where ?元素與你期望的不太一樣,你也可以通過自定義 ?trim ?元素來定制 ?where ?元素的功能。比如,和 ?where ?元素等價的自定義 ?trim ?元素為:

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

?prefixOverrides ?屬性會忽略通過管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子會移除所有 ?prefixOverrides ?屬性中指定的內(nèi)容,并且插入 ?prefix ?屬性中指定的內(nèi)容。

用于動態(tài)更新語句的類似解決方案叫做 ?set?。?set ?元素可以用于動態(tài)包含需要更新的列,忽略其它不更新的列。比如:

<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 ?元素會動態(tài)地在行首插入 ?SET ?關(guān)鍵字,并會刪掉額外的逗號(這些逗號是在使用條件語句給列賦值時引入的)。

來看看與 ?set ?元素等價的自定義 ?trim ?元素吧:

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

注意,我們覆蓋了后綴值設(shè)置,并且自定義了前綴值。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號