MyBatis的動態SQL是基於OGNL表示式的,它可以幫助我們方便的在SQL語句中實現某些邏輯。
一、if標籤此時如果CNAINDCLABASINFID為null,此語句很可能報錯或查詢結果為空。此時我們使用if動態sql語句先進行判斷,如果值為null或等於空字串,我們就不進行此條件的判斷,增加靈活性。
使用if+set標籤修改後,如果某項為null則不進行更新,而是保持資料庫原值。如下示例:
<update id="editRateAnalysTask" parameterType="RateAnalystScale" >UPDATE STUDENT_TBL<set> <if test="studentName != null and studentName != '' "> STUDENT_TBL.STUDENT_NAME = #{studentName}, </if> <if test="studentSex != null and studentSex != '' "> STUDENT_TBL.STUDENT_SEX = #{studentSex}, </if> <if test="studentBirthday != null "> STUDENT_TBL.STUDENT_BIRTHDAY = #{studentBirthday}, </if> <if test="studentPhoto != null "> STUDENT_TBL.STUDENT_PHOTO = #{studentPhoto, javaType=byte[], jdbcType=BLOB, typeHandler=org.apache.ibatis.type.BlobTypeHandler}, </if> <if test="classId != '' "> STUDENT_TBL.CLASS_ID = #{classId} </if> <if test="placeId != '' "> STUDENT_TBL.PLACE_ID = #{placeId} </if></set>WHERE STUDENT_TBL.STUDENT_ID = #{studentId};</update>
四、choose (when,otherwise)有時候我們並不想應用所有的條件,而只是想從多個選項中選擇一個。而使用if標籤時,只要test中的表示式為true,就會執行if標籤中的條件。MyBatis提供了choose 元素。if標籤是與(and)的關係,而choose標籤是或(or)的關係。
choose標籤是按順序判斷其內部when標籤中的test條件是否成立,如果有一個成立,則choose結束。當choose中所有when的條件都不滿則時,則執行otherwise中的sql。類似於Java 的switch 語句,choose為switch,when為case,otherwise則為default。
例如下面例子,同樣把所有可以限制的條件都寫上,方便使用。choose會從上到下選擇一個when標籤的test為true的sql執行。安全考慮,我們使用where將choose包起來,放置關鍵字多於錯誤。
<select id=""> SELECT ST.STUDENT_ID, ST.STUDENT_NAME, ST.STUDENT_SEX, ST.STUDENT_BIRTHDAY, ST.STUDENT_PHOTO, ST.CLASS_ID, ST.PLACE_ID FROM STUDENT_TBL ST <where> <choose> <when test="studentName !=null "> ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName, jdbcType=VARCHAR}),'%') </when > <when test="studentSex != null and studentSex != '' "> AND ST.STUDENT_SEX = #{studentSex, jdbcType=INTEGER} </when > <when test="studentBirthday != null "> AND ST.STUDENT_BIRTHDAY = #{studentBirthday, jdbcType=DATE} </when > <when test="classId != null and classId!= '' "> AND ST.CLASS_ID = #{classId, jdbcType=VARCHAR} </when > <when test="classEntity != null and classEntity.classId !=null and classEntity.classId !=' ' "> AND ST.CLASS_ID = #{classEntity.classId, jdbcType=VARCHAR} </when > <when test="placeId != null and placeId != '' "> AND ST.PLACE_ID = #{placeId, jdbcType=VARCHAR} </when > <when test="placeEntity != null and placeEntity.placeId != null and placeEntity.placeId != '' "> AND ST.PLACE_ID = #{placeEntity.placeId, jdbcType=VARCHAR} </when > <when test="studentId != null and studentId != '' "> AND ST.STUDENT_ID = #{studentId, jdbcType=VARCHAR} </when > <otherwise> </otherwise> </choose> </where></select>
五、trim標籤trim元素的主要功能是可以在自己包含的內容前加上某些字首,也可以在其後加上某些字尾,與之對應的屬性是prefix和suffix;可以把包含內容的首部某些內容覆蓋,即忽略,也可以把尾部的某些內容覆蓋,對應的屬性是prefixOverrides和suffixOverrides。正因為trim有這樣的功能,所以我們也可以非常簡單的利用trim來代替where/set標籤的功能,示例程式碼如下:
trim代替where標籤:
select * from user <trim prefix="WHERE" prefixoverride="AND |OR"> <if test="name != null and name.length()>0"> AND name=#{name}</if> <if test="gender != null and gender.length()>0"> AND gender=#{gender}</if> </trim>
假如說name和gender的值都不為null的話列印的SQL為:select * from user where name = 'xx' and gender = 'xx'
在紅色標記的地方是不存在第一個and的,上面兩個屬性的意思如下:
prefix:字首
prefixoverride:去掉第一個and或者是or
trim代替set標籤:
update user <trim prefix="set" suffixoverride="," suffix=" where id = #{id} "> <if test="name != null and name.length()>0"> name=#{name} , </if> <if test="gender != null and gender.length()>0"> gender=#{gender} , </if> </trim>
假如說name和gender的值都不為null的話列印的SQL為:update user set name='xx' , gender='xx' where id='x'
在紅色標記的地方不存在逗號,而且自動加了一個set字首和where字尾,上面三個屬性的意義如下,其中prefix意義如上:
suffixoverride:去掉最後一個逗號(也可以是其他的標記,就像是上面字首中的and一樣)
suffix:字尾
六、foreach 標籤foreach的主要用在構建in條件中,它可以在SQL語句中進行迭代一個集合。foreach元素的屬性主要有item,index,collection,open,separator,close。
item表示集合中每一個元素進行迭代時的別名;index指定一個名字,用於表示在迭代過程中,每次迭代到的位置;open表示該語句以什麼開始;separator表示在每次進行迭代之間以什麼符號作為分隔符;close表示以什麼結束;在使用foreach的時候最關鍵的也是最容易出錯的就是 collection 屬性,該屬性是必須指定的,但是在不同情況下,該屬性的值是不一樣的,主要有一下3種情況:
如果傳入的是單引數且引數型別是一個List的時候,collection屬性值為list如果傳入的是單引數且引數型別是一個array陣列的時候,collection的屬性值為array如果傳入的引數是多個的時候,我們就需要把它們封裝成一個Map了,當然單引數也可以封裝成map,實際上如果你在傳入引數的時候,在MyBatis裡面也是會把它封裝成一個Map的,map的key就是引數名,所以這個時候collection屬性值就是傳入的List或array物件在自己封裝的map裡面的key1. 單引數List的型別:<select id="dynamicForeachTest" resultType="Blog"> select * from t_blog where id in <foreach collection="list" index="index" item="item" open="(" separator="," close=")"> #{item} </foreach> </select>
上述collection的值為list,對應的Mapper是這樣的:
public List<Blog> dynamicForeachTest(List<Integer> ids);
2. 單引數array陣列的型別:
<select id="dynamicForeach2Test" resultType="Blog"> select * from t_blog where id in <foreach collection="array" index="index" item="item" open="(" separator="," close=")"> #{item} </foreach> </select>
上述collection為array,對應的Mapper程式碼:
public List<Blog> dynamicForeach2Test(int[] ids);
3. 自己把引數封裝成Map的型別
<select id="dynamicForeach3Test" resultType="Blog"> select * from t_blog where title like "%"#{title}"%" and id in <foreach collection="ids" index="index" item="item" open="(" separator="," close=")"> #{item} </foreach> </select>
上述collection的值為ids,是傳入的引數Map的key,對應的Mapper程式碼:
public List<Blog> dynamicForeach3Test(Map<String, Object> params);