Mybatis動(dòng)態(tài)SQL的使用方法

Mybatis的強(qiáng)大特性之一便是它的動(dòng)態(tài)SQL治力。在實(shí)際開發(fā)中,數(shù)據(jù)庫(kù)的查詢比較復(fù)雜勃黍,需要在不同的邏輯中執(zhí)行不同的SQL語(yǔ)句宵统。我們往往要根據(jù)各種不同的場(chǎng)景拼接出不同的SQL語(yǔ)句,而Mybatis給我們提供了動(dòng)態(tài)SQL覆获,可以讓我們根據(jù)具體的業(yè)務(wù)邏輯來(lái)拼接SQL語(yǔ)句马澈。(Mybatis采用功能強(qiáng)大的基于OGNL的表達(dá)式來(lái)淘汰其他的大部分元素

if條件(簡(jiǎn)單的條件判斷)

用戶可以選擇其中的任意某些字段或者都不選,這個(gè)時(shí)候我們的查詢語(yǔ)句該怎么寫呢弄息。 其實(shí)很簡(jiǎn)單痊班,我們只需要寫一些動(dòng)態(tài)的sql就可以實(shí)現(xiàn)這一功能。如下代碼摹量,只需要在拼接查詢條件前辩块,先用<if>是否為null,如果不為null,則執(zhí)行代碼時(shí)會(huì)把條件拼接在<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>

現(xiàn)在回到“if”示例废亭,這次我們將“ACTIVE = 1”也設(shè)置成動(dòng)態(tài)的條件国章,看看會(huì)發(fā)生什么。

<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 元素只會(huì)在至少有一個(gè)子元素的條件返回 SQL 子句的情況下才去插入“WHERE”子句豆村。而且液兽,若語(yǔ)句的開頭為“AND”或“OR”,where 元素也會(huì)將它們?nèi)コ?/p>

test屬性

test的屬性用于條件判斷的語(yǔ)句中掌动,它在Mybatis中廣泛使用四啰。它的作用相當(dāng)于判斷真假。在大部分場(chǎng)景中我們都是用它判斷空和非空粗恢。有時(shí)候我們需要判斷字符串柑晒、數(shù)字和枚舉等。

choose(選擇其中的一項(xiàng))

有時(shí)我們不想應(yīng)用到所有的條件語(yǔ)句眷射,而只想從中擇其一項(xiàng)匙赞。針對(duì)這種情況,MyBatis提供了 choose元素妖碉,它有點(diǎn)像 Java 中的switch 語(yǔ)句 我們來(lái)看一個(gè)簡(jiǎn)單的例子:

<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(簡(jiǎn)化SQL語(yǔ)句中where條件判斷)

在上面的案例中小伙伴們可能都發(fā)現(xiàn)了一個(gè)問(wèn)題涌庭,就是我們?cè)谔砑硬樵儣l件的時(shí)候,在查詢條件之前都先添加了where 1=1欧宜,然后后面直接在這之后再追加and什么什么的坐榆,那么每次這樣來(lái)寫顯然有點(diǎn)麻煩,有沒有簡(jiǎn)單一點(diǎn)的方案呢冗茸?當(dāng)然有席镀,我們可以通過(guò)where元素簡(jiǎn)化SQL語(yǔ)句中的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元素中有條件成立愉昆,才會(huì)將where關(guān)鍵字組裝到SQL中,這樣就比前一種方式簡(jiǎn)單許多麻蹋。

trim(替換和添加)

trimt元素就意味著我們需要去掉一些特殊的字符串跛溉,prefix代表的語(yǔ)句中的前綴,而prefixOverrides代表的是你需要去掉的那種字符串扮授,我們可以將and替換為where芳室,如下:

<select id="getUser4" resultMap="map">
        SELECT * FROM user2
        <!--這個(gè)語(yǔ)句中是把AND換成where,下面的寫法基本與where是等效的-->
        <trim prefix="where" prefixOverrides="and">
            AND id=1
        </trim>
</select>

這個(gè)最終執(zhí)行的sql是SELECT * FROM user2 where id=1刹勃。

set(主要用于更新)

set是我們?cè)诟卤淼臅r(shí)候使用的元素堪侯,通過(guò)set元素,我們可以逐字段的修改一條數(shù)據(jù)荔仁,如下:

<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元素中伍宦,如果遇到了逗號(hào)芽死,系統(tǒng)會(huì)自動(dòng)將之去除。

foreach(主要用于IN語(yǔ)句中)

foreach元素用來(lái)遍歷集合次洼,比如我想查詢多個(gè)城市的人关贵,我的sql語(yǔ)句可能是這樣SELECT * FROM user2 WHERE address IN('西安','北京')卖毁,我在查詢的時(shí)候可能只是傳入了一個(gè)list集合揖曾,該集合中有西安和北京兩個(gè)查詢條件,那我如何將這個(gè)集合組裝成一個(gè)sql語(yǔ)句呢亥啦?很簡(jiǎn)單炭剪,如下:

<!--foreach用于迭代數(shù)據(jù)的元素
    open表示開始的符號(hào)
    close表示結(jié)束符號(hào)
    seprator表示元素間的分隔符
    items表示迭代的數(shù)組
-->
<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表示傳入的參數(shù)中集合的名稱,index表示是當(dāng)前元素在集合中的下標(biāo)翔脱,openclose則表示如何將集合中的數(shù)據(jù)包裝起來(lái)奴拦,separator表示分隔符,item則表示循環(huán)時(shí)的當(dāng)前元素届吁。這樣一段配置最終組合成的sql就是SELECT * FROM user2 WHERE address IN('西安'错妖,'北京')

注意 你可以將任何可迭代對(duì)象(如 List瓷产、Set 等)站玄、Map 對(duì)象或者數(shù)組對(duì)象傳遞給*foreach*作為集合參數(shù)枚驻。當(dāng)使用可迭代對(duì)象或者數(shù)組時(shí)濒旦,index 是當(dāng)前迭代的次數(shù),item 的值是本次迭代獲取的元素再登。當(dāng)使用 Map 對(duì)象(或者 Map.Entry 對(duì)象的集合)時(shí)尔邓,index 是鍵,item 是值

bind(預(yù)定義變量)

使用bind元素我們可以預(yù)先定義一些變量锉矢,然后在查詢語(yǔ)句中使用梯嗽,如下:

<select id="getUserByName" resultMap="">
        <bind name="un" value="username+'%'"></bind>
            SELECT* FROM user2 WHERE user_name LIKE #{un}
</select>

OGNL(Object-Graph Navigation Language )表達(dá)式

Mybatis的動(dòng)態(tài)SQL和${}形式的參數(shù)中都用到了OGNL表達(dá)式,所以我們有必要了解OGNL的簡(jiǎn)單用法沽损。Mybatis常用的OGNL表達(dá)式如下:

OGNL表達(dá)式 含義
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) 調(diào)用對(duì)象方法
e.property 對(duì)象屬性值
e1[e2] 按索引取值(List形入、數(shù)組和)

參考資料

https://blog.csdn.net/u012702547

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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市缝左,隨后出現(xiàn)的幾起案子亿遂,更是在濱河造成了極大的恐慌浓若,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛇数,死亡現(xiàn)場(chǎng)離奇詭異挪钓,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)苞慢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門诵原,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人挽放,你說(shuō)我怎么就攤上這事绍赛。” “怎么了辑畦?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵吗蚌,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我纯出,道長(zhǎng)蚯妇,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任暂筝,我火速辦了婚禮箩言,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘焕襟。我一直安慰自己陨收,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布鸵赖。 她就那樣靜靜地躺著务漩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪它褪。 梳的紋絲不亂的頭發(fā)上饵骨,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音茫打,去河邊找鬼居触。 笑死,一個(gè)胖子當(dāng)著我的面吹牛老赤,可吹牛的內(nèi)容都是我干的轮洋。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼诗越,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼砖瞧!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起嚷狞,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤块促,失蹤者是張志新(化名)和其女友劉穎荣堰,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體竭翠,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡振坚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了斋扰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片渡八。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖传货,靈堂內(nèi)的尸體忽然破棺而出屎鳍,到底是詐尸還是另有隱情,我是刑警寧澤问裕,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布逮壁,位于F島的核電站,受9級(jí)特大地震影響粮宛,放射性物質(zhì)發(fā)生泄漏窥淆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一巍杈、第九天 我趴在偏房一處隱蔽的房頂上張望忧饭。 院中可真熱鬧,春花似錦筷畦、人聲如沸词裤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)亚斋。三九已至作媚,卻和暖如春攘滩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纸泡。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工漂问, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人女揭。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓蚤假,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親吧兔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子磷仰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 1. 簡(jiǎn)介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL境蔼、存儲(chǔ)過(guò)程以及高級(jí)映射的優(yōu)秀的...
    笨鳥慢飛閱讀 5,453評(píng)論 0 4
  • MyBatis 動(dòng)態(tài)SQL 內(nèi)容 Mybatis動(dòng)態(tài)SQL在XML中支持的幾種標(biāo)簽: if chose trim灶平、...
    lihongyan閱讀 8,361評(píng)論 1 10
  • 書本近幾年與我已漸行漸遠(yuǎn)伺通,不是不喜歡看書,也不是不喜歡閱讀逢享,而是時(shí)間越來(lái)越多被電子設(shè)備占據(jù)罐监。而不管是手機(jī)、IPA...
    鴻哲閱讀 234評(píng)論 1 0
  • 收獲滿滿的一個(gè)下午! 看到六六在BetterMe深圳營(yíng)發(fā)的用思維導(dǎo)圖做年度規(guī)劃的沙龍活動(dòng)侧但,立刻報(bào)名矢空,一是為了面...
    童童小瑾書閱讀 978評(píng)論 0 1
  • 閑談詩(shī)歌與生活· 田 秀 有人拿生活擺菜來(lái)說(shuō)詩(shī),其實(shí),我看沒有不妥的地方.不過(guò),拿這種方式去解釋詩(shī)與生活的關(guān)系,我...
    興安居士閱讀 270評(píng)論 0 2