Mybatis動態SQL的使用方法

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(替換和添加)

trimt元素就意味著我們需要去掉一些特殊的字符串,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表示是當前元素在集合中的下標,openclose則表示如何將集合中的數據包裝起來,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、數組和)

參考資料

https://blog.csdn.net/u012702547

http://www.mybatis.org/mybatis-3/zh/dynamic-sql.html

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,646評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,595評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,560評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,814評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,224評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,444評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,988評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,804評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,998評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,237評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,706評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,993評論 2 374

推薦閱讀更多精彩內容

  • 1. 簡介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優秀的...
    笨鳥慢飛閱讀 5,561評論 0 4
  • MyBatis 動態SQL 內容 Mybatis動態SQL在XML中支持的幾種標簽: if chose trim、...
    lihongyan閱讀 8,387評論 1 10
  • 書本近幾年與我已漸行漸遠,不是不喜歡看書,也不是不喜歡閱讀,而是時間越來越多被電子設備占據。而不管是手機、IPA...
    鴻哲閱讀 237評論 1 0
  • 收獲滿滿的一個下午! 看到六六在BetterMe深圳營發的用思維導圖做年度規劃的沙龍活動,立刻報名,一是為了面...
    童童小瑾書閱讀 984評論 0 1
  • 閑談詩歌與生活· 田 秀 有人拿生活擺菜來說詩,其實,我看沒有不妥的地方.不過,拿這種方式去解釋詩與生活的關系,我...
    興安居士閱讀 283評論 0 2