公司項目中一直使用Mybatis作為持久層框架,自然,動態sql寫得也比較多了,最常見的莫過於在查詢語句中使用if標簽來動態地改變過濾條件了。Mybatis的強大特性之一便是它的動態sql,免除了拼接sql帶來的各種麻煩,在開發項目的過程中,常見的和不常見的你都有可能會用到,現在就來把這一塊總結一下。
if
<select id="getCategory" parameterType="EshopShopCategory" resultMap="EshopCategory" > SELECT * from CATEGORY t WHERE (1=1) <if test="shopCategoryId!=null"> AND t.category_id =#{shopCategoryId} </if> <if test="shopCategoryName!=null"> AND t.CATEGORY_NAME like '%${shopCategoryName}%' </if> <if test="shopId==null"> AND t.shop_id=0 </if> ORDER BY SEQUENCE_NO </select>
這通常用於多條件組合查詢。
<insert id="addCategory" parameterType="EshopCategory"> insert into CATEGORY( <if test="shopCategoryName!=null and shopCategoryName!='' "> shop_category_name, </if> <if test="shopId!=null and shopId!=''"> shop_id, </if> ADD_TIME) values( <if test="shopCategoryName!=null and shopCategoryName!=''"> #{shopCategoryName,jdbcType=VARCHAR}, </if> <if test="shopId!=null and shopId!=''"> #{shopId,jdbcType=NUMERIC}, </if> current_timestamp )
</insert>
這適用於數據庫有默認值的時候可以不讓插入空值。
<update id="updateProductCategory" parameterType="EshopShopCategory" > update CATEGORY t set <if test="shopCategoryName!=null"> t.category_name=#{shopCategoryName,jdbcType=VARCHAR}, </if> <if test="updateUser!=null"> t.update_user=#{updateUser,jdbcType=VARCHAR} , </if> t.update_time=current_timestamp where t.shop_category_id=#{shopCategoryId,jdbcType=NUMERIC} </update>
這條動態地修改語句用得非常多,是因為很多時候我們在做修改操作時並不確定到底要修改哪些字段(哪些屬性),可能有的需要保存原值不變,這時候就可以做動態的sql,你新建一個對象後將需要修改的字段附上新值,這樣不用修改的屬性在這個對象上表現地是null,調用這個動態的sql時便可以完成部分修改。
choose,when,otherwise
適用場景:我們不想用到所有的條件語句,而只想從中擇其一二。針對這種情況,MyBatis 提供了 choose 元素,它有點像 Java 中的 switch 語句。(我感覺它有點像提供多種條件規則時,而這些規則又可以綜合寫在一起時)
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <choose> <when test="title != null"> AND title like #{title} </when> <when test="author != null and author.name != null"> AND author_name like #{author.name} </when> <otherwise> AND featured = 1 </otherwise> </choose> </select>
到目前為止,我還沒有用到過choose,以後多留意。
trim,where,set
為了避免當if動態條件都不成立時,或者第一個條件不成立第二個條件成立時出現諸如"select * from TableA where"或者"select * from TableA and where"病態sql,我們可以使用trim,where,set標簽來解決。
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG <where> <if test="state != null"> state = #{state} </if> <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </where> </select>
在實際應用中,我通常是不寫where標簽,而在where關鍵字之後加上1=1的條件。即不管有無動態條件,總可以得到完整的sql:select * from A where 1=1。。。
<update id="updateAuthorIfNecessary"> update Author <set> <if test="username != null">username=#{username},</if> <if test="password != null">password=#{password},</if> <if test="email != null">email=#{email},</if> <if test="bio != null">bio=#{bio}</if> </set> where id=#{id} </update>
foreach
foreach有時候在項目中會遇到,而且不止一次,用的時候是需要動點腦子的。通常用於篩選出在多個值組成的一個集合中或者排除多個值的場景,說白了,也就是我們之前寫sql時用到in、not in的時候:(集合是動態不確定的,需要從前台傳值過來)
<select id="selectNumInOrder" resultType="String"> select count(0) from order a left join item b on a.ORDER_ID = b.ORDER_ID where a.STATUS in ('1','2','3','5') <if test="list.size() > 0"> and b.PHONE_NUM in <foreach item="numberList" collection="list" open="(" separator="," close=")"> #{numberList.num} </foreach> </if> </select>
<select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST P WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>
foreach 元素的功能是非常強大的,它允許你指定一個集合,聲明可以用在元素體內的集合項和索引變量。它也允許你指定開閉匹配的字符串以及在迭代中間放置分隔符。這個元素是很智能的,因此它不會偶然地附加多余的分隔符。
注意 你可以將一個 List 實例或者數組作為參數對象傳給 MyBatis,當你這麼做的時候,MyBatis 會自動將它包裝在一個 Map 中並以名稱為鍵。List 實例將會以“list”作為鍵,而數組實例的鍵將是“array”。
以上是結合http://mybatis.github.io/mybatis-3/zh/getting-started.html及自己開發中比較常用的總結出來的,今天給梳理一下,分享給大家!