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,常用的元素也就這些了。