1. 程式人生 > >mybatis中動態sql的實現與使用

mybatis中動態sql的實現與使用

首先引用一段mybatis文件中的話:

動態 SQL

    MyBatis 的強大特性之一便是它的動態 SQL。如果你有使用 JDBC 或其它類似框架的經驗,你就能體會到根據不同條件拼接 SQL 語句的痛苦。例如拼接時要確保不能忘記新增必要的空格,還要注意去掉列表最後一個列名的逗號。利用動態 SQL 這一特性可以徹底擺脫這種痛苦。

     雖然在以前使用動態 SQL 並非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 對映語句中的強大的動態 SQL 語言得以改進這種情形。

     動態 SQL 元素和 JSTL 或基於類似 XML 的文字處理器相似。在 MyBatis 之前的版本中,有很多元素需要花時間瞭解。MyBatis 3 大大精簡了元素種類,現在只需學習原來一半的元素便可。MyBatis 採用功能強大的基於 OGNL 的表示式來淘汰其它大部分元素。

一、if

二、where

三、set

四、trim

五、choose, when, otherwise

六、foreach

七、bind


 

下面記錄各個元素的巧妙使用:

一、if

如果採用xml的方式配置mybatis,假設現在要做兩個查詢:

1.查詢一個物件的所有記錄。

2.查詢一個物件所有記錄中包含一個傳過來的字串的模糊查詢。

那麼不使用動態SQL應該這樣寫:(這樣顯得很麻煩)

<select id="productList" resultType="Product">
    select p.id,p.name,p.price from product p
</select>
<select id="getProductsLikeName" parameterType="String" resultType="Product">
    select p.id,p.name,p.price from product p where name like concat('%',#{nameaa},'%')
</select>

對應介面:

List<Product> productList();
List<Product> getProductsLikeName(String name);

採用if:如果沒有傳入Product物件就查詢所有,傳入了物件就根據product.name的值進行模糊查詢,方便太多了。

<select id="list" resultType="Product" parameterType="Product">
    select p.id,p.name,p.price from product p
    <if test="name!=null">
        where name like concat('%',#{name},'%')
    </if>
</select>

對應介面:

List<Product> list();
List<Product> list(Product product);

二、where

如果有多個if來判斷,前一個if不成立,可能就會出現多出一個and的錯誤情況。

where>標籤會進行自動判斷

如果任何條件都不成立,那麼就在sql語句裡就不會出現where關鍵字

如果有任何條件成立,會自動去掉多出來的 and 或者 or。

例如:除了根據name模糊查詢,再加一個價格的篩選。

(如果不用where只用兩個if,

    假設name沒有傳值,那麼sql語句就會變成  select p.id,p.name,p.price from product p and price>#{price}

    這顯然會報錯。

 )

<select id="list" resultType="Product" parameterType="Product">
    select p.id,p.name,p.price from product p
   <where>
       <if test="name!=null">
           and name like concat('%',#{name},'%')
       </if>
       <if test="price!=null">
           and price>#{price}
       </if>
   </where>
</select>

三、set

在update語句裡也會碰到多個欄位相關的問題。 在這種情況下,就可以使用set標籤:

name或者price有值的時候才進行sql拼接。

<update id="updateProduct" parameterType="Product" >
    update product
    <set>
        <if test="name!=null">name=#{name},</if>
        <if test="price!=null">price=#{price}</if>
    </set>
    where id=#{id}
</update>

四、trim

如果 where 元素沒有按正常套路出牌,我們可以通過自定義 trim 元素來定製 where 元素的功能。比如,和 where 元素等價的自定義 trim 元素為:

prefixOverrides 屬性會忽略通過管道分隔的文字序列(注意此例中的空格也是必要的)。它的作用是移除所有指定在 prefixOverrides 屬性中的內容,並且插入 prefix 屬性中指定的內容。

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

例子:這裡把<where>改為了<trim prefix="WHERE" prefixOverrides="AND |OR ">。

<select id="list" resultType="Product" parameterType="Product">
    select p.id,p.name,p.price from product p
    <trim prefix="WHERE" prefixOverrides="AND |OR ">
       <if test="name!=null">
           and name like concat('%',#{name},'%')
       </if>
       <if test="price!=null">
           and price>#{price}
       </if>
    </trim>
</select>

例子:<set>改為了<trim prefix="SET" suffixOverrides=",">。

特別注意:我看的文件中提示出如果最後一個if不成立,刪去的是字尾值,同時添加了字首值。那麼sql語句的結尾就會多出一個逗號。

<update id="updateProduct" parameterType="Product" >
    update product
    <trim prefix="SET" suffixOverrides=",">
        <if test="name!=null">name=#{name},</if>
        <if test="price!=null">price=#{price}</if>
    </trim>
    where id=#{id}
</update>

五、choose, when, otherwise

有時我們不想應用到所有的條件語句,而只想從中擇其一項。針對這種情況,MyBatis 提供了 choose 元素,它有點像 Java 中的 switch 語句。

例子:如果傳入的Product物件沒有設定name和price的值,那麼就執行查詢id大於1的記錄,如果name或price有值,那麼就查詢對應的,並且不執行<otherwise>中的語句。 非常的像switch語句。

<select id="list1" resultType="Product">
    SELECT p.id,p.name,p.price FROM product p
    <where>
        <choose>
            <when test="name != null">
                and name like concat('%',#{name},'%')
            </when>
            <when test="price !=null and price != 0">
                and price > #{price}
            </when>
            <otherwise>
                and id >1
            </otherwise>
        </choose>
    </where>
</select>

六、foreach

foreach標籤通常用於in 這樣的語法裡。

例子:查詢id為1和4的記錄。

<select id="list3" resultType="Product">
    SELECT p.id,p.name,p.price FROM product p
    WHERE ID in
    <foreach item="item" index="index" collection="list"
             open="(" separator="," close=")">
        #{item}
    </foreach>
</select>

七、bind

bind 元素可以從 OGNL 表示式中建立一個變數並將其繫結到上下文。

<!-- 本來的模糊查詢方式 -->
<!--         <select id="list4" resultType="Product"> -->
<!--             select p.id,p.name,p.price from   product p  where name like concat('%',#{0},'%') -->
<!--         </select> -->

<select id="list4" resultType="Product">
    <bind name="likename" value="'%' + name + '%'" />
    select p.id,p.name,p.price from   product p  where name like #{likename}
</select>

引用書籍中的話:

bind取代模糊查詢的好處是提高了程式碼的可移植性。

在進行模糊查詢時,如果是MySQL資料庫,常常用到的是一個concat,它用'%'和引數相連。然而在Oracle資料庫則沒有,Oracle資料庫用連線符號”||“。 當我們有了bind元素,就不必使用資料庫語言,而是使用MyBatis的動態SQL即可完成。

所以無論是MySQL還是Oracle都可以使用這樣的語句,從而提高了程式碼的可移植性。