關於Mybatis動態sql中test的坑點總結

總結Mybatis動態sql中test的坑

在mybatis中要實現動態sql,重要方式就是使用test,通過其中表達式返回的true、false來達到動態sql的拼接。隨著業務的復雜,test中的判斷將會越來越復雜,所以熟悉test中細節處理對動態sql來說尤為重要。

判斷相等的註意點

== 少打一個=

現在我們有一個Integer類型的參數typeId,需要當typeId等於1的時候拼接一串sql,mybatis的xml如下:

<if test="count == 1">
    AND ISNULL(t.count)
</if>

這段代碼沒問題,但有一個隱藏的風險,假如你少打一個 = 這段test將會始終返回ture這種邏輯錯誤mybatis會吞掉,所以養成判斷時常量寫在前變量寫在後是有必要的習慣,適用於很多語言,這種風格尤其適用像js這類語言,其實java不經常出現這種等價錯誤,不過還是建議養成習慣,因為你以後可能接觸其他語言。

所以如果這樣寫

test="count == 1"
//當少打瞭一個等號
test="count = 1"//很不幸,這mybatis擅作主張的處理為返回瞭count,true、false將會由count決定

test="1 == count"
//當少打瞭一個等號
test="1 = count" //執行時,mybatis會很友好的給你拋個異常

判斷字符是否相等

現在我們有一個String類型的參數type,需要當type等於字符串AI的時候拼接一串sql,mybatis的xml如下

<if test="type== 'AI' ">
    AND t.type = 1
</if>

動態sql標簽的小陷阱

現在MyBatis越來越受大傢的喜愛瞭,它的優勢大傢都知道,我就不多說瞭,直接說重點。

MyBatis中提供動態SQL功能,我們可以使用<if><when><where><otherwise><foreach>等等,這樣我們就可以寫出根據條件生成的動態SQL瞭,但是,在這中間,我們經常用到的<if>標簽有一個小誤區,一不小心就會掉下去

下面先舉個正常的例子

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

在上面的例子中,當title不等於null時,<if>標簽中間的條件才會被拼接上,這樣,SQL語句就是動態的瞭。

但是,當我們對所有條件進行判斷時,你是否會這樣寫:

<select id="findActiveBlogWithTitleLike" 
     parameterType="Blog" resultType="Blog">
  SELECT * FROM BLOG 
  WHERE
  <if test="userId != null">
     state = ‘ACTIVE' 
  </if>

  <if test="title != null">
    AND title like #{title}
  </if>
</select>

沒問題吧?至少語法上不錯的,至少它可以正常生成一個SQL。

但是,不知道你註意到瞭沒,當所有條件都為null的時候,會出現什麼情況?

SELECT * FROM BLOG 
  WHERE

看到瞭吧?這樣的SQL能成功執行麼?

答案當然是NO。

那麼該怎麼辦?那就要記住瞭,當你寫動態SQL時候,先考慮一下會不會產生所有條件都不成立的情況,會不會出現隻有一個WHERE而沒有條件的情況,那麼你要做的就是加一個<where>標簽將所有條件包起來。

<select id="findActiveBlogWithTitleLike" 
     parameterType="Blog" resultType="Blog">
  SELECT * FROM BLOG 
 <where>
  <if test="userId != null">
     state = ‘ACTIVE' 
  </if>

  <if test="title != null">
    AND title like #{title}
  </if>
 </where>
</select>

這樣,當所有條件都不成立時,WHERE也不會被拼上。

這時,有機靈的小夥伴發現瞭,如果第一個條件不成立,第二個成立,那SQL會不會變成這樣?

 SELECT * FROM BLOG 
     WHERE
    AND title like #{title}

這個就放心好瞭,當你用<if>標簽包圍條件後,它會自動去掉AND的。

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。 

推薦閱讀: