1. 程式人生 > >MyBatis實戰之動態SQL

MyBatis實戰之動態SQL

如果使用JDBC或者其他框架,很多時候你得根據需要去拼接SQL,這是一個麻煩的事情,而MyBatis提供對SQL語句動態的組裝能力,而且它只有幾個基本的元素,非常簡單明瞭,大量的判斷都可以在MyBatis的對映XML檔案裡面配置,以達到許多我們需要大量程式碼才能實現的功能,大大減少了我們編寫程式碼的工作量,這體現了MyBatis的靈活性、高度可配置性和可維護性。MyBatis也可以在註解中配置SQL,但是由於註解中配置功能受限,對於複雜的SQL而言可讀性很差,所以使用較少。

關於MyBatis的註解使用可以參考我的這篇文章MyBatis實戰之初步

今天主要講解這麼幾個常用的動態SQL:

1.if

2.choose、when、otherwise

3.trim、where、set

4.foreach

5.test

6.bind

一、if

if通常與where一起連用比較多

如下程式碼所示:

    <select id="selectName"  parameterType="String" resultMap="BaseResultMap">
       select <include refid="Base_Column_List"/>
       from `user`
       <where>
       <if test="userName!=''">
       and user_name 
= #{userName} </if> </where> </select>

<if>中的test通常判斷的條件是不等於Null或者空字串,除此之外還可以進行比較判斷比如大於等於小於等這樣的。

二、choose、when、otherwise

 <select id="selectName"  parameterType="String" resultMap="BaseResultMap">
       select <include refid="Base_Column_List"/>
       from `user`       
       
<choose> <when test="userName!=null and userName!=''"> where userName = #{userName} </when> <otherwise> where sex = #{sex} </otherwise> </choose> </select>

你可以將<choose><when></when><otherwise></otherwise></choose>理解為Java中的if-else或者是if-else if-else

三、trim、where、set

trim+where示例:

    <select id="selectName"  parameterType="String" resultMap="BaseResultMap">
       select <include refid="Base_Column_List"/>
       from `user`       
       <trim prefix="where" prefixOverrides="AND |OR">
          <if test="userName !=null and userName!=''">
          and user_name = #{userName}
          </if>
       </trim>
    </select>
    

prefix:字首      

prefixoverride:去掉第一個and或者是or

trim+set示例:

 update user

  <trim prefix="set" suffixoverride="," suffix=" where id = #{id} ">

    <if test="name != null and name.length()>0"> name=#{name} , </if>

    <if test="gender != null and gender.length()>0"> gender=#{gender} ,  </if>

  </trim>

prefix同trim+where的意思是一樣,都是字首。

suffixoverride:去掉最後一個逗號(也可以是其他的標記,就像是上面字首中的and一樣)

suffix:字尾

四、foreach

批量更新示例:

 <update id="udpateUserLogoStatu" parameterType="java.util.List">
   
 <foreach collection="users" item="user" index="index" separator=";">
        update `user`
        <set>
            logo = 1
        </set>
        where logo = #{user.logo}
    </foreach>     
 
 </update>

foreach相關引數解釋:

collection配置的users是傳遞進來的引數名稱,它可以是一個數組或者List、Set等集合;

item配置的是迴圈中當前的元素;

index配置的是當前元素在集合的位置下標;

separator是各個元素的間隔符;

還有程式碼中沒有展示的open和close,它們的含義是以什麼符號將這些元素包裝起來。

在SQL中對於in語句我們常常使用,對於大量資料的in語句需要我們特別注意,因為它會消耗大量的效能,還有一些資料庫的SQL對執行的SQL長度也有限制。所以我們使用它的時候需要預估一下這個collection物件的長度。

五、test

至於test就不提太多了,在<where>+<if>中用到非常頻繁。

六、bind

bind通常用於繫結引數,然後引用,在實際開發中用的也不少。

bind的示例:

<select id="getUserList" resultType="com.blog.entity.User">
          <!-- bind:可以將OGNL表示式的值繫結到一個變數中,方便後來引用這個變數的值 -->
          <bind name="userName" value="'%'+userName+'%'"/> eName是employee中一個屬性值
          SELECT * FROM `user`
          <if test="userName!=null">
            where ename like #{userName}
          </if>
</select>

動態SQL一般常見的問題,就是查詢條件出錯,一般要麼是引數問題,或者是多個欄位and拼接出問題。

另外還有一點要提醒,在要用動態SQL之前,最好還是將SQL先執行一遍,確定沒有問題後,再改為動態SQL,最後再單元測試多個邊界條件測試下,確保沒有問題後,再編寫對應的邏輯Controller。