來源:北大青鳥總部 2023年03月06日 09:30
作為一名優(yōu)秀的Java后端工程師,不得不說,跟數(shù)據(jù)庫打交道的次數(shù)比跟自己女朋友(程序猿沒有女朋友,原諒我這個(gè)不那么恰當(dāng)?shù)谋扔鳎┮黄鸪燥埖拇螖?shù)都多;所以很多程序員對寫SQL是深惡痛絕啊,但是回過頭來一想,程序在跟數(shù)據(jù)庫進(jìn)行交互的時(shí)候,不就是靠的SQL來完成的嗎?如果連SQL都不寫了,那還怎么能更好的了解數(shù)據(jù)庫?怎么跟數(shù)據(jù)庫親切交流呢?后端工程師豈不是要失業(yè)了。
基于以上種種,MyBatis作為一個(gè)優(yōu)秀、輕巧、靈活的持久層框架,既解決了我們和數(shù)據(jù)庫交互的繁瑣的代碼,同時(shí)也滿足了我們寫SQL的愿望(真正是因?yàn)槲覀冏约簩慡QL的可以優(yōu)化SQL的執(zhí)行效率),其中最大的一個(gè)特點(diǎn),就是MyBatis的所提供的動(dòng)態(tài)SQL,這也是它有別于其他ORM框架最大的一個(gè)特點(diǎn),相信大家都使用過JDBC或其他類似框架的經(jīng)驗(yàn),你應(yīng)該能體會(huì)到根據(jù)不同條件拼接SQL語句有多么難受;經(jīng)常會(huì)因?yàn)橐粋€(gè)空格或者分號等,到時(shí)程序運(yùn)營錯(cuò)誤,動(dòng)態(tài)SQL出現(xiàn)徹底的幫我們擺脫這一痛苦。
所以今天這篇文章,就來跟大家聊一聊MyBatis的動(dòng)態(tài)SQL是怎么樣一回事兒,是怎么幫廣大程序猿節(jié)省出時(shí)間去陪女朋友的(哦哦哦...我有錯(cuò)了,程序猿沒有女朋友...)
MyBatis給我們提供很多的動(dòng)態(tài)SQL語句,這里我們就說幾種常用的動(dòng)態(tài)SQL:
<if>
<choose>
<trim>
<foreach>
接下來咱么就分別來介紹下這幾種常用的動(dòng)態(tài)SQL。
首先,我們先來說說標(biāo)簽,這個(gè)標(biāo)簽從字面意義上就可以很只管的看出來,它就是一個(gè)用來做判斷的語句,和Java中的if語句一樣,所以它的作用就是用來判斷我們拼接的SQL中的條件是否成立,接下來上代碼:
<select parameterType="int" resultType="test.User"> SELECT * FROM t_user WHERE 1=1 <if test="userId !=null and userId !=''"> and id = #{userId}; </if> </select> |
在這里我們就用來是判斷傳遞過來的參數(shù)userId是否為空的情況,這里大家可能注意到一個(gè)點(diǎn),就是有個(gè)where 1=1 以及標(biāo)簽里有個(gè)and,這是因?yàn)椋绻覀冊谑褂脴?biāo)簽的時(shí)候,傳遞過來的是多個(gè)條件,這就需要多個(gè)標(biāo)簽了,所以通常情況下我們在每個(gè)標(biāo)簽中的條件前面加一個(gè)and將它們拼接起來,因?yàn)槲覀儾淮_定那個(gè)標(biāo)簽里的條件是滿足的,隨意where后面第一滿足的條件前就多了一個(gè)and關(guān)鍵字,所以就通常情況下就會(huì)在where后面加上一個(gè)1=1恒成立的條件。
注:這里如果大家不使用 1=1的話,可以使用標(biāo)簽,來替換where 1=1 這個(gè)等式,將條件寫在標(biāo)簽里就可以了。
翻譯一下就是選擇的意思,也就是他可以幫我么在多個(gè)條件中選擇一個(gè)成立的條件,它有點(diǎn)像 Java 中的 switch 語句,一個(gè)標(biāo)簽中還需要另外兩個(gè)重要的標(biāo)簽、 在后面解釋,還是先上代碼。
<select parameterType="int" resultType="test.User"> SELECT * FROM t_user <where> <choose> <when test="userId != null and userId != ''"> and id =#{userId} </when> <otherwise> and id=3 </otherwise> </choose> </where> </select> |
這段代碼中,我們就直接改掉了標(biāo)簽來代替where 1=1,這里解釋下。
當(dāng)test屬性的條件滿足時(shí),是執(zhí)行拼接其內(nèi)的條件。
所有條件都不滿足時(shí),拼接其內(nèi)的條件。
看標(biāo)簽的名字就能猜個(gè)八九不離十了,這個(gè)標(biāo)簽可以自定義一些動(dòng)態(tài)SQL的功能,怎么個(gè)定義法呢?咱們還是先來上代碼,一睹為快。
<select parameterType="int" resultType="test.User"> SELECT * FROM t_user <trim prefix="where" prefixOverrides="and | or"> <if test="userId !=null and userId !=''"> and id = #{userId}; </if> </trim> </select> |
還記得我們在說標(biāo)簽的時(shí)候,說到的標(biāo)簽嗎,用它可以代替where 1=1的情況,現(xiàn)在我們學(xué)習(xí)了標(biāo)簽的話,也可以用這種方式,標(biāo)簽中有四個(gè)屬性。
prefix 前綴的意思,上圖中我們給的值是where意思就是會(huì)這個(gè)位置拼接上一個(gè)where關(guān)鍵字,當(dāng)然也可以是別的關(guān)鍵字,如:set
prefixOverrides 前覆蓋的意思,上圖中它會(huì)把標(biāo)簽中的and,關(guān)鍵字自動(dòng)去掉,其他關(guān)鍵字就可以直接用|隔開。
suffix 后綴的意思,和前綴相反,可以在SQL末尾添加執(zhí)行的后綴。
suffixOverrides 后綴覆蓋的意思,和前綴覆蓋相反,通常會(huì)把SQL最后無用的分號自動(dòng)去掉。
以上就是標(biāo)簽的用法,它是一個(gè)非常靈活的標(biāo)簽,所以通常有些復(fù)雜的SQL的時(shí)候,就可以用它來處理。
這個(gè)標(biāo)簽也很容易理解,就是循環(huán)的意思,和Java中的for循環(huán)類似,只不過他里面的屬性多些。
<insert> insert into t_user (name,age) values <foreach collection="userList" item="user" separator=","> (#{user.username},#{user.age}) </foreach> </insert> |
元素的屬性主要有item、index、collection、open、separator、close
collection 表示如何來得到這個(gè)集合,如果傳入的直接為一個(gè)List,那么collection值就為list。
如果直接傳入的為一個(gè)array不可變數(shù)組,那么collection值就為array,如果傳入的為一個(gè)Map,那么collection的值就為map的key。
item 表示集合中每一個(gè)元素進(jìn)行迭代時(shí)的別名,比如item為value,那么,每次獲取的都使用#{value}即可。
index 指定一個(gè)名字,用于表示在迭代過程中,每次迭代到的位置,一般很少使用這個(gè)。
open 表示該語句以什么開始。
separator 表示在每次進(jìn)行迭代之間以什么符號作為分隔符。
close 表示以什么結(jié)束。
標(biāo)簽通常用在批量處理的數(shù)據(jù)的時(shí)候,通常是傳遞一些集合或者數(shù)組的參數(shù),在拼接SQL的時(shí)候,就需要先從這些集合或數(shù)組總循環(huán)取出這些數(shù)據(jù),比如:批量插入數(shù)據(jù),批量刪除數(shù)據(jù)。
好了,到此就把MyBatis最重要也是最核心的一部分內(nèi)容常用的動(dòng)態(tài)SQL給大家介紹了一下,其中在說一些SQL的是,也會(huì)說下相關(guān)聯(lián)的動(dòng)態(tài)SQL標(biāo)簽,這部分知識必須要掌握哦。