1. 程式人生 > >Mybatis動態SQL常用標籤

Mybatis動態SQL常用標籤

動態 SQL     

MyBatis 的強大特性之一便是它的動態 SQL。如果你有使用 JDBC 或其它類似框架的經驗,你就能體會到根據不同條件拼接 SQL 語句的痛苦。例如拼接時要確保不能忘記新增必要的空格,還要注意去掉列表最後一個列名的逗號。利用動態 SQL 這一特性可以徹底擺脫這種痛苦。

MyBatis 提供了可以被用在任意 SQL 對映語句中的強大的動態 SQL 語言得以改進這種情形。     

動態 SQL 元素和 JSTL 或基於類似 XML 的文字處理器相似。在 MyBatis 之前的版本中,有很多元素需要花時間瞭解。MyBatis 3 大大精簡了元素種類,現在只需學習原來一半的元素便可。MyBatis 採用功能強大的基於 OGNL 的表示式來淘汰其它大部分元素。

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

 

一、if 標籤       

動態 SQL 通常要做的事情是根據條件包含 where 子句的一部分

拼接條件的時候,加了一個恆等條件(1=1),避免多出and 

	public List<User> getUserBylike(@Param("username") String username,
					@Param("state") Integer state);

        <select id="getUserBylike" resultType="cn.jq.mybatis.model.User">
		select * from t_user where 1=1
		<if test="username != null and username != ''">
			and username like #{username}
		</if>
		<if test="state != null and state >= 0">
			and state like #{state}
		</if>
	</select>
List<User> userList = userMapper.getUserBylike("%a%",1);

select * from t_user where 1=1 and username like ? and state like ? 

強調一下:

    1)在介面中最好加@Param註解,以防止以下異常ReflectionException: There is no getter for property named...

    2)if標籤裡的test屬性裡是用的OGNL表示式,這是apache下的一個標籤,用法類似jstl,但有些小差別,具體的內容可以在ognl官網上查詢,有些特殊符號在xml檔案裡不能直接使用,可以在w3cschool裡查

http://www.w3school.com.cn/tags/html_ref_entities.html,比如:雙引號(< 使用 &lt;)

二、where標籤

上面恆等條件(1=1),避免多出and ,但是,Mybatis提供了一種解決辦法就是where標籤,

where 元素只會在至少有一個子元素的條件返回 SQL 子句的情況下才去插入“WHERE”子句。而且,若語句的開頭為“AND”或“OR”,where 元素也會將它們去除。

	<select id="getUserBylike" resultType="cn.jq.mybatis.model.User">
		select * from t_user 
		<where>
			<if test="username != null and username != ''">
				and username like concat('%',concat(#{username},'%'))   
			</if>
			<if test="state != null and state >= 0">
				and state like #{state}
			</if>
		</where>
	</select>
List<User> userList = userMapper.getUserBylike("a",1);

select * from t_user WHERE username like concat('%',concat(?,'%')) and state like ? 

注意:where標籤只能去掉語句的開頭為“AND”或“OR” ,並不能去掉後面的,如果我們非要寫在後面,這時可以通過自定義 trim 元素來定製 where 元素的功能。

 

三、 trim 標籤(自定義 trim 元素)

四個屬性:

prefix:加字首

prefixOverrides:移除所有指定在 prefixOverrides 屬性中的內容,並且插入 prefix 屬性中指定的內容

suffix:加字尾

suffixOverrides:如果發現字串後有某個字尾,把它幹掉

	<select id="getUserBylike" resultType="cn.jq.mybatis.model.User">
		select * from t_user 
		<trim prefix="where" suffixOverrides="AND|OR">
			<if test="username != null and username != ''">
				username like #{username} and
			</if>
			<if test="state != null and state >= 0">
				state like #{state} and
			</if>
		</trim>
	</select>

 

四、set標籤

用於動態更新語句的解決方案叫做 setset 元素可以用於動態包含需要更新的列,而捨去其它的

	public boolean updateUser(User user);
	<update id="updateUser" parameterType="cn.jq.mybatis.model.User">
		update t_user 
		<set>
			<if test="username != null and username != ''">
				username=#{username},
			</if>
			<if test="pazzword != null and pazzword != ''">
				pazzword=#{pazzword},
			</if>
			<if test="state != null and state != ''">
				state=#{state},
			</if>
			<if test="regDate != null">
				reg_date=#{regDate},
			</if>
		</set>
		where id=#{id}
	</update>

這裡,set 元素會動態前置 SET 關鍵字,同時也會刪掉無關的逗號,因為用了條件語句之後很可能就會在生成的 SQL 語句的後面留下這些逗號。(譯者注:因為用的是“if”元素,若最後一個“if”沒有匹配上而前面的匹配上,SQL 語句的最後就會有一個逗號遺留)       

若你對 set 元素等價的自定義 trim 元素的程式碼感興趣,那這就是它的真面目:

	<update id="updateUser" parameterType="cn.jq.mybatis.model.User">
		update t_user 
		<trim prefix="SET" suffixOverrides=",">
				<if test="username != null and username != ''">
					username=#{username},
				</if>
				<if test="pazzword != null and pazzword != ''">
					pazzword=#{pazzword},
				</if>
				<if test="state != null and state != ''">
					state=#{state},
				</if>
				<if test="regDate != null">
					reg_date=#{regDate},
				</if>
		</trim>
		where id=#{id}
	</update>

五、choose (when, otherwise)標籤

有時我們不想應用到所有的條件語句,而只想從中擇其一項。針對這種情況,MyBatis 提供了 choose 元素,它有點像 Java 中的 switch...case,從上到下匹配,找到匹配的條件,就結束匹配其他的!

	<select id="getUserBylike" resultType="cn.jq.mybatis.model.User">
		select * from t_user where
		<choose>
			<when test="username != null and username != ''">
				username like #{username}
			</when>
			<when test="state != null and state >= 0">
				state like #{state}
			</when>
			<otherwise>
				1=1
			</otherwise>
		</choose>
	</select>

六、foreach標籤

動態 SQL 的另外一個常用的操作需求是對一個集合進行遍歷,通常是在構建 IN 條件語句的時候

	//通過一組id值查詢對應的user
	public List<User> selectUserByIds(@Param("ids") int[] ids);

	<select id="selectUserByIds" resultType="cn.jq.mybatis.model.User">
		select * from t_user where id in 
		<foreach collection="ids" item="id" separator="," open="(" close=")">
			#{id}
		</foreach>
	</select>
		 	int[] ids = new int[] {1,2};
			List<User> userList = userMapper.selectUserByIds(ids);
			System.out.println(Arrays.asList(userList));
----
select * from t_user where id in ( ? , ? )

collection="ids" : 介面上傳過來的數值或list集合或者map集合都可以

item="id" :設定遍歷集合或數組裡的每一個值的迭代變數

separator="," : 因為要構造出 (1,2,3)這種樣子的字串,設定中間的分隔符

open="(" : 因為要構造出 (1,2,3)這種樣子的字串,設定字首的符號(

close=")": 因為要構造出 (1,2,3)這種樣子的字串,設計結尾的字尾)

index: 瞭解,陣列或list集合的時候,設定索引變數,如果是Map集合就是map的key的迭代變數

 

foreach 元素的功能非常強大, 對於不同資料庫之間的批量操作也是經常使用。

七、bind標籤(瞭解)

bind 元素可以從 OGNL 表示式中建立一個變數並將其繫結到上下文

上面例子中的模糊查詢 傳參,使用bind元素 拼接 % 號, 注意不能傳null值

	<select id="getUserBylike" resultType="cn.jq.mybatis.model.User">
		<bind name="new_username" value="'%'+username+'%'"/>
		select * from t_user where
		<choose>
			<when test="username != null and username != ''">
				username like #{new_username}
			</when>
			<when test="state != null and state >= 0">
				state like #{state}
			</when>
			<otherwise>
				1=1
			</otherwise>
		</choose>
	</select>