Mybatis
的強大特性之一便是它的動態SQL
。在實際開發中,數據庫的查詢比較復雜,需要在不同的邏輯中執行不同的SQL語句。我們往往要根據各種不同的場景拼接出不同的SQL語句,而Mybatis
給我們提供了動態SQL,可以讓我們根據具體的業務邏輯來拼接SQL語句。(Mybatis采用功能強大的基于OGNL的表達式來淘汰其他的大部分元素)
if條件(簡單的條件判斷)
用戶可以選擇其中的任意某些字段或者都不選,這個時候我們的查詢語句該怎么寫呢。 其實很簡單,我們只需要寫一些動態的sql就可以實現這一功能。如下代碼,只需要在拼接查詢條件前,先用<if>
是否為null
,如果不為null
,則執行代碼時會把條件拼接在<where>
后
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</select>
現在回到“if”示例,這次我們將“ACTIVE = 1”
也設置成動態的條件,看看會發生什么。
<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 元素只會在至少有一個子元素的條件返回 SQL 子句的情況下才去插入“WHERE”子句。而且,若語句的開頭為“AND”或“OR”,where 元素也會將它們去除。
test屬性
test
的屬性用于條件判斷的語句中,它在Mybatis
中廣泛使用。它的作用相當于判斷真假。在大部分場景中我們都是用它判斷空和非空。有時候我們需要判斷字符串、數字和枚舉等。
choose(選擇其中的一項)
有時我們不想應用到所有的條件語句,而只想從中擇其一項。針對這種情況,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>
where(簡化SQL語句中where條件判斷)
在上面的案例中小伙伴們可能都發現了一個問題,就是我們在添加查詢條件的時候,在查詢條件之前都先添加了where 1=1
,然后后面直接在這之后再追加and什么什么的,那么每次這樣來寫顯然有點麻煩,有沒有簡單一點的方案呢?當然有,我們可以通過where元素簡化SQL語句中的where條件,如下:
<select id="getUser3" resultMap="u">
SELECT * FROM user2
<where>
<choose>
<when test="id!=null">
AND id=#{id}
</when>
<when test="address!=null">
AND address=#{address}
</when>
<when test="username!=null">
AND user_name LIKE concat(#{username},'%')
</when>
<otherwise>
AND 10>id
</otherwise>
</choose>
</where>
</select>
這樣,只有where元素中有條件成立,才會將where關鍵字組裝到SQL中,這樣就比前一種方式簡單許多。
trim(替換和添加)
trim
t元素就意味著我們需要去掉一些特殊的字符串,prefix
代表的語句中的前綴,而prefixOverrides
代表的是你需要去掉的那種字符串,我們可以將and替換為where,如下:
<select id="getUser4" resultMap="map">
SELECT * FROM user2
<!--這個語句中是把AND換成where,下面的寫法基本與where是等效的-->
<trim prefix="where" prefixOverrides="and">
AND id=1
</trim>
</select>
這個最終執行的sql是SELECT * FROM user2 where id=1
。
set(主要用于更新)
set是我們在更新表的時候使用的元素,通過set元素,我們可以逐字段的修改一條數據,如下:
<update id="update">
UPDATE user2
<set>
<if test="username!=null">
user_name=#{username},
</if>
<if test="password!=null">
password=#{password}
</if>
</set>
WHERE id=#{id}
</update>
在set元素中,如果遇到了逗號,系統會自動將之去除。
foreach(主要用于IN語句中)
foreach
元素用來遍歷集合,比如我想查詢多個城市的人,我的sql語句可能是這樣SELECT * FROM user2 WHERE address IN('西安','北京')
,我在查詢的時候可能只是傳入了一個list集合,該集合中有西安和北京兩個查詢條件,那我如何將這個集合組裝成一個sql語句呢?很簡單,如下:
<!--foreach用于迭代數據的元素
open表示開始的符號
close表示結束符號
seprator表示元素間的分隔符
items表示迭代的數組
-->
<select id="getUserInCities" resultMap="BaseResultMap">
SELECT * FROM user2
WHERE address IN
<foreach collection="cities" index="index" open="(" separator="," close=")" item="city">
#{city}
</foreach>
</select>
collection
表示傳入的參數中集合的名稱,index
表示是當前元素在集合中的下標,open
和close
則表示如何將集合中的數據包裝起來,separator
表示分隔符,item
則表示循環時的當前元素。這樣一段配置最終組合成的sql就是SELECT * FROM user2 WHERE address IN('西安','北京')
。
注意 你可以將任何可迭代對象(如 List、Set 等)、Map 對象或者數組對象傳遞給
*foreach*
作為集合參數。當使用可迭代對象或者數組時,index 是當前迭代的次數,item 的值是本次迭代獲取的元素。當使用 Map 對象(或者 Map.Entry 對象的集合)時,index 是鍵,item 是值
bind(預定義變量)
使用bind元素我們可以預先定義一些變量,然后在查詢語句中使用,如下:
<select id="getUserByName" resultMap="">
<bind name="un" value="username+'%'"></bind>
SELECT* FROM user2 WHERE user_name LIKE #{un}
</select>
OGNL(Object-Graph Navigation Language )表達式
在Mybatis
的動態SQL和${}形式的參數中都用到了OGNL表達式,所以我們有必要了解OGNL的簡單用法。Mybatis常用的OGNL表達式如下:
OGNL表達式 | 含義 |
---|---|
e1 or e2 | |
e1 and e2 | |
e1 == e2 或 e1 eq e2 | |
e1 != e2 或 e1 neq e2 | |
e1 lt e2(小于) | |
e1 lte e2(小于等于,gt(大于),gte(大于等于)) | |
e1 + e2、e1*e2、e1/e2、e1-e2、e1%e2 | |
!e 或 not e | 非 |
e.method(args) | 調用對象方法 |
e.property | 對象屬性值 |
e1[e2] | 按索引取值(List、數組和) |