主要用於解決查詢條件不確定的情況,比如前台表單提交用於在Controller里生成一個pojo類,如果用戶並沒有完全提交一個pojo類的所有字段,那么Controller接收到的pojo類是包含一些null的,所有在SQL查詢的時候不用去理會這些Null,根據查詢傳入的內容不同,SQL語句也相應的修改,這就是Mybatis所支持的動態SQL。
1、IF
IF關鍵字通常出現在WHERE語句中,通過判斷某個參數值的是否滿足某個條件,如是否存在,是否大於給定的閾值等來決定是否在WHERE語句中加入針對該條件的判斷
1.1 WHERE中使用IF
下面的if標簽就很好的解決了上述問題,首先根據傳入的pojo類判斷該類的name字段是否為null,如果不為Null才會根據該類的name字段去查詢。相應的操作也針對了email字段,即先判斷是否不為Null,不為null才會查詢。
<select id="selectByUser" resultType="pojo.User"> select * from user2 where 1=1 <if test="name != null and name != ''"> and name like concat('%',#{name},'%') </if> <if test="email !=null and email!=''"> and email like concat('%',#{email},'%') </if> </select>
用email為null的測試類User去測試,發現email字段沒有參與到SQL查詢。
@Test public void testSQL(){ User user = new User(); user.setName("aaa"); testDao.selectByUser(user); }

雖然沒有看源碼,但我是感覺底層就是一個sql拼串的過程,有兩個細節需要注意:
- 直接使用where結合if標簽,如果所有的WHERE條件都是if標簽來判斷,需要在最外層加上一個1=1的條件判斷,否則如果所有if標簽不滿足,那么就會產生一個沒有where語句的sql,不符合sql語法規則。
- 對String類如本例中的name email進行判斷的時候,首先要判斷是否為null,避免空指針異常
- if語句中的and需要手動添加
其實根據上面這幾個要點,堅定了我動態SQL底層就是字符串拼串的猜測。
1.2 UPDATE中使用IF
在update語句中使用動態SQL可以解決類似 對一個用戶的記錄只更新該用戶發生了變化的字段。if標簽的使用同上。
<update id="updateUserSelective"> update user2 set <if test="name!=null and name!=''"> name = #{name}, </if> <if test="email!=null and email!=''"> email = #{emai}, </if> id=#{id} where id=#{id} </update>
注意:
- 同樣也需要一些dump的條件來保證所有if標簽都不生效的時候SQL語句不會出現語法錯誤,比如where id=id set id=id。但其實這樣也不能完全保證不出錯,萬一id也沒有呢?所有者需要service層的協助,動態SQL只能保證最大程度的SQL不出現語法錯誤
- 逗號!!!逗號!!!!逗號!!!在動態SQL的時候經常會出現一些低級的SQL語法錯誤,所有多看日志
- 對於支持動態SQL的Dao層方法一般以Selective結尾
1.3 INSERT中使用IF
很別扭,越寫越別扭。
<insert id="insertUserSelective"> INSERT into user2 (<if test="name != null and name!=''"> name,</if> id ) values ( <if test="name != null and name!=''"> #{name} </if>, #{id} ) </insert>
注意:
- dummy條件id
- 把dummy條件寫在最后,防止逗號出現錯誤
2、 choose用法
