MyBatis動態SQL第一篇之實現多條件查詢(if、where、trim標簽)


一、動態SQL概述

以前在使用JDBC操作數據時,如果查詢條件特別多,將條件串聯成SQL字符串是一件痛苦的事情。通常的解決方法是寫很多的if-else條件語句對字符串進行拼接,並確保不能忘了空格或在字段的最后省略逗號。MyBatis使用動態SQL來改善這種情形,動態SQL是基於OGNL的表達式,可方便我們在SQL語句中實現某些邏輯。用於實現動態SQL的元素如下。

  • if:利用if實現簡單的條件選擇
  • choose(when,otherwise):相當於Java中的switch語句,通常與when和otherwise搭配使用
  • set:解決動態更新語句
  • trim:可以靈活的去除多余的關鍵字
  • foreach:迭代一個集合,通常用於in條件

二、if用法

在查詢條件不是很多並且較為固定的情況下,最好的解決方案是采用多參數直接入參的方式,這樣代碼比較清晰,可讀性強。如下

public interface UserMappper{
    public List<User> getUserList(@Param("userName") String userName,
                                  @Param("userRole") Integer roleId);
}
<select id="getUserList" resultMap="userList">
  select u.*, r.roleName from smbms_user u, smbms_role r
  where u.userName like connect ('%', #{userName}, '%')
  and u.userRole=#{userRole} and u.userRole=r.id
</select>

在上述代碼中,參數使用了@Param注解,並將參數roleId重命名為userRole

測試上述代碼,如下

  • 在兩個條件都給出的情況下,如String userName="孫"; Integer roleId=3,此時會輸出正確結果;
  • 若傳入的用戶角色roleId為空,即只按用戶名稱進行模糊查詢,如String userName="孫"; Integer roleId=null,此時輸出的結果不滿足需求:沒有輸入用戶角色的情況下,只根據用戶名稱進行模糊查詢的需求;
  • 若傳入的用戶用戶名稱userName為“”(空字符串),roleId有值(roleId=3),此時結果是正確的;

針對上述這種某字段用戶輸入可能為空的情況,我們使用動態SQL的if元素來實現多條件查詢,如下

<select id="getUserList" resultMap="userList">
  select u.*, r.roleName from smbms_user u, smbms_role r where u.userRole=r.id <if test="userRole != null"> and u.userRole = #{userRole}
    </if>
    <if test="userName != null and userName != ''"> and u.userName like concat('%', #{userName}, '%')
    </if>
</select>

在上述代碼中,利用if元素實現簡單的條件判斷,if元素的test屬性表示進入if內需要滿足的條件。此時對於String userName="孫"; Integer roleId=null這種情況,輸出了正確結果。

三、if+where用法

單表查詢,考慮如下代碼

<select id="getUserList" resultType="User">
  select * from smbms_user where <if test="userName != null and userName != ''">
      u.userName like concat('%', #{userName}, '%')
    </if>
    <if test="userRole != null"> and u.userRole = #{userRole}
    </if>
</select>

此時對於String userName=""; Integer roleId=3這種情況,會報錯,因為多了一個“and”。

針對這種and、where的處理,可使用動態SQL的where元素,where元素主要用來簡化SQL語句中的where條件判斷,並智能的處理and和or,不必擔心多余關鍵字導致的語法錯誤。如下

<select id="getUserList" resultType="User">
  select * from smbms_user
    <where>
      <if test="userName != null and userName != ''"> and u.userName like concat('%', #{userName}, '%')
      </if>
      <if test="userRole != null"> and u.userRole = #{userRole}
      </if>
    </where>
</select> 

where元素標簽會自動標識其標簽內是否有返回值,若有,就插入一個where。此外,若該標簽返回的內容是以and或者or開頭的,會自動剔除。此時對於String userName=""; Integer roleId=3這種情況會正確輸出

四、if+trim用法

除了where元素之外,還可以使用trim元素來替代where元素,並實現與where元素相同的效果。

trim元素也會自動識別其標簽內是否有返回值,若有返回值,則在自己包含的內容前加上某些前綴,也可以在其后加上某些后綴,與之對應的屬性是prefix和suffix;trim也可把包含內容首部的某些內容覆蓋(即忽略),或者把尾部的某些內容覆蓋,與之對應的屬性是prefixOverrieds和suffixOverrieds。

<select id="getUserList" resultType="User">
  select * from smbms_user
  <trim prefix="where" prefixOverrides="and | or">
    <if test="userName != null and userName != ''">
      and u.userName like concat('%', #{userName}, '%')
    </if>
    <if test="userRole != null">
      and u.userRole = #{userRole}
    </if>
  </trim>
</select>

prefixOverrides:對於trim包含內容的首部進行指定內容的忽略


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM