關(guān)于Mybatis動(dòng)態(tài)sql中test的坑點(diǎn)總結(jié)
總結(jié)Mybatis動(dòng)態(tài)sql中test的坑
在mybatis中要實(shí)現(xiàn)動(dòng)態(tài)sql,重要方式就是使用test,通過(guò)其中表達(dá)式返回的true、false來(lái)達(dá)到動(dòng)態(tài)sql的拼接。隨著業(yè)務(wù)的復(fù)雜,test中的判斷將會(huì)越來(lái)越復(fù)雜,所以熟悉test中細(xì)節(jié)處理對(duì)動(dòng)態(tài)sql來(lái)說(shuō)尤為重要。
判斷相等的注意點(diǎn)
== 少打一個(gè)=
現(xiàn)在我們有一個(gè)Integer類型的參數(shù)typeId,需要當(dāng)typeId等于1的時(shí)候拼接一串sql,mybatis的xml如下:
<if test="count == 1"> ? ? AND ISNULL(t.count) </if>
這段代碼沒(méi)問(wèn)題,但有一個(gè)隱藏的風(fēng)險(xiǎn),假如你少打一個(gè) = 這段test將會(huì)始終返回ture這種邏輯錯(cuò)誤mybatis會(huì)吞掉,所以養(yǎng)成判斷時(shí)常量寫(xiě)在前變量寫(xiě)在后是有必要的習(xí)慣,適用于很多語(yǔ)言,這種風(fēng)格尤其適用像js這類語(yǔ)言,其實(shí)java不經(jīng)常出現(xiàn)這種等價(jià)錯(cuò)誤,不過(guò)還是建議養(yǎng)成習(xí)慣,因?yàn)槟阋院罂赡芙佑|其他語(yǔ)言。
所以如果這樣寫(xiě)
test="count == 1" //當(dāng)少打了一個(gè)等號(hào) test="count = 1"http://很不幸,這mybatis擅作主張的處理為返回了count,true、false將會(huì)由count決定 test="1 == count" //當(dāng)少打了一個(gè)等號(hào) test="1 = count" //執(zhí)行時(shí),mybatis會(huì)很友好的給你拋個(gè)異常
判斷字符是否相等
現(xiàn)在我們有一個(gè)String類型的參數(shù)type,需要當(dāng)type等于字符串AI的時(shí)候拼接一串sql,mybatis的xml如下
<if test="type== 'AI' "> ? ? AND t.type = 1 </if>
動(dòng)態(tài)sql標(biāo)簽的小陷阱
現(xiàn)在MyBatis越來(lái)越受大家的喜愛(ài)了,它的優(yōu)勢(shì)大家都知道,我就不多說(shuō)了,直接說(shuō)重點(diǎn)。
MyBatis中提供動(dòng)態(tài)SQL功能,我們可以使用<if><when><where><otherwise><foreach>等等,這樣我們就可以寫(xiě)出根據(jù)條件生成的動(dòng)態(tài)SQL了,但是,在這中間,我們經(jīng)常用到的<if>標(biāo)簽有一個(gè)小誤區(qū),一不小心就會(huì)掉下去
下面先舉個(gè)正常的例子
<select id="findActiveBlogWithTitleLike"? ? ? ?parameterType="Blog" resultType="Blog"> ? SELECT * FROM BLOG? ? WHERE state = ‘ACTIVE'? ? <if test="title != null"> ? ? AND title like #{title} ? </if> </select>
在上面的例子中,當(dāng)title不等于null時(shí),<if>標(biāo)簽中間的條件才會(huì)被拼接上,這樣,SQL語(yǔ)句就是動(dòng)態(tài)的了。
但是,當(dāng)我們對(duì)所有條件進(jìn)行判斷時(shí),你是否會(huì)這樣寫(xiě):
<select id="findActiveBlogWithTitleLike"? ? ? ?parameterType="Blog" resultType="Blog"> ? SELECT * FROM BLOG? ? WHERE ? <if test="userId != null"> ? ? ?state = ‘ACTIVE'? ? </if> ? <if test="title != null"> ? ? AND title like #{title} ? </if> </select>
沒(méi)問(wèn)題吧?至少語(yǔ)法上不錯(cuò)的,至少它可以正常生成一個(gè)SQL。
但是,不知道你注意到了沒(méi),當(dāng)所有條件都為null的時(shí)候,會(huì)出現(xiàn)什么情況?
SELECT * FROM BLOG? ? WHERE
看到了吧?這樣的SQL能成功執(zhí)行么?
答案當(dāng)然是NO。
那么該怎么辦?那就要記住了,當(dāng)你寫(xiě)動(dòng)態(tài)SQL時(shí)候,先考慮一下會(huì)不會(huì)產(chǎn)生所有條件都不成立的情況,會(huì)不會(huì)出現(xiàn)只有一個(gè)WHERE而沒(méi)有條件的情況,那么你要做的就是加一個(gè)<where>標(biāo)簽將所有條件包起來(lái)。
<select id="findActiveBlogWithTitleLike"? ? ? ?parameterType="Blog" resultType="Blog"> ? SELECT * FROM BLOG? ?<where> ? <if test="userId != null"> ? ? ?state = ‘ACTIVE'? ? </if> ? <if test="title != null"> ? ? AND title like #{title} ? </if> ?</where> </select>
這樣,當(dāng)所有條件都不成立時(shí),WHERE也不會(huì)被拼上。
這時(shí),有機(jī)靈的小伙伴發(fā)現(xiàn)了,如果第一個(gè)條件不成立,第二個(gè)成立,那SQL會(huì)不會(huì)變成這樣?
?SELECT * FROM BLOG? ? ? ?WHERE ? ? AND title like #{title}
這個(gè)就放心好了,當(dāng)你用<if>標(biāo)簽包圍條件后,它會(huì)自動(dòng)去掉AND的。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot AOP控制Redis自動(dòng)緩存和更新的示例
今天小編就為大家分享一篇關(guān)于SpringBoot AOP控制Redis自動(dòng)緩存和更新的示例,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-01-01關(guān)于Selenium的UI自動(dòng)化測(cè)試屏幕截圖功能實(shí)例代碼
今天小編就為大家分享一篇關(guān)于Selenium的UI自動(dòng)化測(cè)試屏幕截圖功能實(shí)例代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-05-05idea新建Springboot項(xiàng)目,設(shè)置默認(rèn)maven和jdk版本方式
這篇文章主要介紹了idea新建Springboot項(xiàng)目,設(shè)置默認(rèn)maven和jdk版本方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12小議Java的源文件的聲明規(guī)則以及編程風(fēng)格
這篇文章主要介紹了小議Java的源文件的聲明規(guī)則以及編程風(fēng)格,僅給Java初學(xué)者作一個(gè)簡(jiǎn)單的示范,需要的朋友可以參考下2015-09-09Java8中Optional的一些常見(jiàn)錯(cuò)誤用法總結(jié)
我們知道 Java 8 增加了一些很有用的 API, 其中一個(gè)就是 Optional,下面這篇文章主要給大家介紹了關(guān)于Java8中Optional的一些常見(jiàn)錯(cuò)誤用法的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2018-07-07mybatis調(diào)用mysql存儲(chǔ)過(guò)程并獲取返回值方式
這篇文章主要介紹了mybatis調(diào)用mysql存儲(chǔ)過(guò)程并獲取返回值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08spring boot 配置freemarker及如何使用freemarker渲染頁(yè)面
springboot中自帶的頁(yè)面渲染工具為thymeleaf 還有freemarker這兩種模板引擎,本文重點(diǎn)給大家介紹spring boot 配置freemarker及如何使用freemarker渲染頁(yè)面,感興趣的朋友一起看看吧2023-10-10