Mybatis學習筆記(6)-動態SQL

卡巴拉的樹發表於2018-02-12

Mybatis學習筆記(6)-動態SQL
MyBatis學習筆記(1)—使用篇

MyBatis學習筆記(2)—對映關係篇

MyBatis學習筆記(3)—高階對映之一對一對映

Mybatis學習筆記(4)-高階對映之一對多對映

Mybatis學習筆記(5)-高階對映之多對多對映

Mybatis一項強大的功能就是動態SQL,你可以使用動態SQL為SQL語句帶上一些邏輯,免除使用JDBC時拼裝SQL的痛苦,下面我們來看一些最常見的應用。

if (判斷元素)

我們在程式碼中時常使用if語句來做判斷,而在Mybatis裡,也可以使用if元素,下面我們通過例項來看一個簡單的用法:

<select id="findProductList" parameterType="com.shuqing28.pojo.Products"
        resultType="com.shuqing28.pojo.Products">
    SELECT * FROM products
    WHERE 1=1
    <if test="prodName!=null and prodName!=''">
            AND prod_name like '%${prodName}%'
    </if>
</select>
複製程式碼

這裡我們使用一個if語句來探測prodName是否為空,如果不為空就加上prod_name的模糊匹配,如果引數為空就不構造這個條件。 在這裡我們看到有個WHERE 1=1其實這裡是為了防止後面條件一旦為真,那麼不加上WHERE 1=1的話,查詢語句就變成了SELECT * FROM products AND prod_name like '%${prodName}%' ,直接接上了AND,有問題了。

其實還有幾種方法可以讓我們不使用WHERE 1=1

where, trim, set

針對上面的 WHERE 1=1我們可以使用WHERE元素替代:

<select id="findProductList" parameterType="com.shuqing28.pojo.Products"
        resultType="com.shuqing28.pojo.Products">
    SELECT * FROM products
    <where>
    <if test="prodName!=null and prodName!=''">
            AND prod_name like '%${prodName}%'
    </if>
    </where>
</select>
複製程式碼

where元素裡面的if為真時,它才會把WHERE子句加進去,而且會自動調整AND是否存在。

也可以使用trim來調整格式:

<select id="findProductList" parameterType="com.shuqing28.pojo.Products"
        resultType="com.shuqing28.pojo.Products">
    SELECT * FROM products
    <trim prefix="WHERE" prefixOverrides="AND">
    <if test="prodName!=null and prodName!=''">
            AND prod_name like '%${prodName}%'
    </if>
    </trim>
</select>
複製程式碼

在這裡prefix代表字首,prefixoverride則會去掉第一個AND,所以最後的效果和where元素是一樣的。

而set元素則是應用於更新,加入我們要更新某個欄位:

<update id="updateProduct" parameterType="com.shuqing28.pojo.Products">
    UPDATE products
    <set>
    <if test="prodName!=null and prodName!=''">
            AND prod_name like '%${prodName}%'
    </if>
    </set>
    WHERE prod_id=#{prodId}
</update>
複製程式碼

這裡用set包裹,也就是如果if元素判斷為真,就會自動新增SET子句

UPDATE products SET prod_name like '%${prodName}% WHERE prod_id=#{prodId}
複製程式碼

當然也可以使用trim元素:

<trim prefix="SET" suffixOverride=",">...</trim>
複製程式碼

只要把字首換成SET,suffixOverride則會自動把最後的不需要的,去掉,當然set自帶去最後逗號的功能。

foreach

顯然foreach是一個迴圈語句,它的作用就是遍歷集合,如果傳入的是一個List、Set介面的集合,那麼它就可以大展身手了。 假如有以下的查詢:

SELECT * FROM products WHERE prod_id IN ("ANV01", "ANV02", "ANV03");
複製程式碼

那麼我們可以把3個引數封裝到一個List中,然後用foreach語句遍歷取出:

<select id="findProductListByProdId" parameterType="java.util.List"
        resultType="com.shuqing28.pojo.Products">
    SELECT * FROM products
    WHERE prod_id IN
    <foreach item="prod_id" index="index" collection="list" open="(" separator="," close=")">
            #{prod_id}
    </foreach>
</select>
複製程式碼

再看看使用時是怎麼操作的:

@Test
public void findProductListByProdId(){
    SqlSession sqlSession = sqlSessionFactory.openSession();
    try {
        OrdersDao ordersDao = sqlSession.getMapper(OrdersDao.class);
        List<String> prodList = new ArrayList<String>();
        prodList.add("ANV01");
        prodList.add("ANV02");
        prodList.add("ANV03");
        List<Products> productList = ordersDao.findProductListByProdId(prodList);
        System.out.println(productList);
    } finally {
        sqlSession.close();
    }
}
複製程式碼

構造出查詢引數,直接傳入list即可。

bind

其它的動態SQL引數包括前面一直包含的test,用於在條件判斷元素中測試真假,還有個bind元素,用於定義一個上下文變數,比如我們第一個例子中的%${prodName}%,我們也可以用bind事先定義好:

<select id="findProductList" parameterType="com.shuqing28.pojo.Products"
        resultType="com.shuqing28.pojo.Products">
        <bind name="pattern" value="'%' + _parameter + '%'"/>
    SELECT * FROM products
    WHERE 1=1
    <if test="prodName!=null and prodName!=''">
            AND prod_name like #{pattern}'
    </if>
</select>
複製程式碼

上例中我們預先定義好pattern,使用時就可以直接拿來用了,對於多處使用的變數適合這樣操作,這裡的_parameter代表傳入的引數,它和萬用字元結合後,賦給了pattern

關於動態SQL,常用的元素也就這些了。

相關文章