最近使用Mybatis做爲持久層框架,天然/動態sql寫得也比較多了,最多見的就是在查詢語句中使用if標籤來動態地改變過濾條件。
Mybatis強大特性之一就是它的動態sql,免除了拼接sql帶來的各類麻煩。
在項目開發過程當中,常見的和不常見的問題都有碰到過,因此在這總結一下。
if
choose(when,otherwise)
trim(where,set)
foreach
1.一般用於多條件組合查詢
<select id="productId" parameterType="Product" resultMap="getProduct">
SELECT * FROM PRODUCT t WHERE (1=1)
<if test="Product.productId!=null">
AND t.PRODUCT_ID = #{Product.productId}
</if>
<if test="Product.productName!=null">
AND t.PRODUCT_NAME like '%#{Product.productName}%'
</if>
<if test="Product.inStock!=null">
AND t.PRODUCT.INSTOCK = 0
</if>
ORDER BY SEQUENCE_NO
</select>
2.這適用於數據庫有默認值的時候能夠不讓插入空值
<insert id="addCategory" parameterType="Category">
INSERT INTO CATEGORY(
<if test="categoryName!=null and categoryName!='' ">
CATEGORY_NAME
</if>
<if test="categoryId!=null and categoryId!='' ">
CATEGORY_ID
</if>
ADD_TIME)
VALUES(
<if test="categoryName!=null and categoryName!='' ">
#{categoryName, jdbcType=VARCHAR}
</if>
<if test="categoryId!=null and categoryId!='' ">
#{categoryId, jdbcType=NUMERIC}
</if>
currentTimeStamp
)
</insert>
3.這條動態地修改語句用得很是多,是由於不少時候咱們在作修改操做時並不肯定到底要修改哪些字段(哪些屬性),可能有的須要保存原值不變.
這時候就能夠作動態的sql,你新建一個對象後,將須要修改的字段附上新值,這樣不用修改的屬性在這個對象上表現的是null,調用這個動態的sql時即可以完成部分修改。
<update id="updateCategory" parameterType="Category">
update CATEGORY t SET
<if test="categoryName!=null">
t.CATEGORY_NAME = #{categoryName, jdbcType=VARCHAR},
</if>
<if test="updateUser!=null">
t.UPDATE_USER = #{updateUser, jdbcType=VARCHAR},
</if>
t.UPDATE_TIME = currentTimeStamp
WHERE t.CATEGORY_ID = #{categoryId, jdbcType=NUMERIC}
</update>
4.choose,when,otherwise
適用場景:咱們不想用到全部的條件語句,而只想從中擇其一二。
針對這種狀況,MyBatis 提供了 choose 元素,它有點像 Java 中的 switch 語句。
(我感受它有點像提供多種條件規則時,而這些規則又能夠綜合寫在一塊兒時)
<select id="findInStockLike" resultType="Product">
SELECT * FROM PRODUCT WHERE STATE = 'INSTOCK'
<choose>
<when>
AND TITLE LIKE #{title}
</when>
<when>
AND BRAND_NAME LIKE #{brand.name}
</when>
<otherwise>
AND INMARKETING = 0
</otherwise>
</choose>
</select>
5.where, set, trim
爲了不當if動態條件都不成立時,或者第一個條件不成立第二個條件成立時出現
諸如"select * from TableA where"
或者"select * from TableA and where"病態sql,
咱們可使用where, set, trim標籤來解決。
5.1)where
<select id="findInStockProductLike" resultType="Product">
SELECT * FROM PRODUCT
<when>
<if test="state!=null">
STATE = #{state}
</if>
<if test="title!=null">
AND TITLE LIKE #{title}
</if>
<if test="brand!=null and brand.name!=null">
AND BRAND_NAME LIKE #{brand.name}
</if>
</when>
</select>
在實際應用中,我一般是不寫where標籤,而在where關鍵字以後加上1=1的條件。即無論有無動態條件,總能夠獲得完整的sql:select * from A where 1=1。。。
5.2)set
<update id="updateUserInfo">
UPDATE USER
<set>
<if test="userName!=null">USER_NAME = #{userName}</if>
<if test="userPsw!=null">USER_PSW = #{userPsw}</if>
<if test="userEmail!=null">USER_EMAIL = #{userEmail}</if>
</set>
WHERE USER_ID = #{userId}
</update>
6.foreach
foreach有時候在項目中會遇到,並且不止一次,用的時候是須要動點腦子的。
一般用於篩選出在多個值組成的一個集合中或者排除多個值的場景.
說白了,也就是咱們以前寫sql時用到in、not in的時候:(集合是動態不肯定的,須要從前臺傳值過來)
<select id="selectProdcutNoInOrder" resultType="String">
SELECT COUNT(0) FROM PRODUCT a LEFT JOIN ORDER_INFO b
ON a.PRODUCT_ID = b.PRODUCT_ID
WHERE a.STATUS in('1', '2', '3', '6')
<if test="list.size()>0">
AND b.PHONE_NUM IN
<foreach item="phoneNumList" collection="list" open="(" separator="," close=")">
#{phoneNumList.num}
</foreach>
</if>
</select>
foreach 元素的功能是很是強大的,它容許你指定一個集合,聲明能夠用在元素體內的集合項和索引變量。
它也容許你指定開閉匹配的字符串以及在迭代中間放置分隔符。
這個元素是很智能的,所以它不會偶然地附加多餘的分隔符。
注意,你能夠將一個 List 實例或者數組做爲參數對象傳給 MyBatis,當你這麼作的時候,MyBatis 會自動將它包裝在一個 Map 中並以名稱爲鍵。
List 實例將會以「list」做爲鍵,而數組實例的鍵將是「array」。
<select id="selectProductIn" resultType="com.dowik.dowikmall.Product">
SELECT * FROM PRODUCT p WHERE PRODUCT_ID IN
<foreach item="productIdList" index="index" collection="list" open="(" separetor="," close=")">
#{productIdList}
</foreach>
</select>