MyBatis動(dòng)態(tài)<if>標(biāo)簽使用避坑指南
前言
MyBatis中的<if>動(dòng)態(tài)SQL標(biāo)簽,常用場景是根據(jù)條件添加WHERE子句。本篇文章將對<if>動(dòng)態(tài)SQL標(biāo)簽使用中的常見問題進(jìn)行演示和總結(jié)。
演示的場景有:if判斷字符串,if判斷數(shù)字。
MyBatis版本:3.5.6
正文
一. if標(biāo)簽判斷字符串
查詢參數(shù)Param如下。
public class Param {
private int id;
private String level;
private int times;
private String timestamp;
// 省略get和set
}
語句如下。
<select id="queryEvents" resultMap="eventResultMap">
SELECT
id,
e_name,
e_times,
e_level
FROM event
WHERE id=#{id}
<if test="level != null and level != ''">
AND e_level=#{level}
</if>
</select>
上述是判斷字符串是否為空(null或者空串),不為空時(shí),為WHERE子句添加額外的條件。
通過<if>標(biāo)簽判斷字符串是否為空,是<if>標(biāo)簽使用頻率最高的用法,但是有時(shí)也會(huì)通過<if>標(biāo)簽來判斷字符串的值,這里有多種寫法,下面給出正確寫法,推薦寫法和錯(cuò)誤寫法。
正確寫法1
<select id="queryEvents" resultMap="eventResultMap">
SELECT
id,
e_name,
e_times,
e_level
FROM event
WHERE id=#{id}
<if test="level == 'secondary'">
AND e_times>10
</if>
</select>
注意''單引號中一定需要是多個(gè)字符,如果只有一個(gè)字符,會(huì)報(bào)錯(cuò)。
正確寫法2
<select id="queryEvents" resultMap="eventResultMap">
SELECT
id,
e_name,
e_times,
e_level
FROM event
WHERE id=#{id}
<if test="level == 'secondary'.toString()">
AND e_times>10
</if>
</select>
這種寫法不限制''單引號中的字符個(gè)數(shù),一個(gè)或多個(gè)都可以。
推薦寫法
<select id="queryEvents" resultMap="eventResultMap">
SELECT
id,
e_name,
e_times,
e_level
FROM event
WHERE id=#{id}
<if test='level == "secondary"'>
AND e_times>10
</if>
</select>
推薦外層用單引號,內(nèi)層用雙引號的寫法,能少踩很多坑。
特別注意:錯(cuò)誤寫法
<select id="queryEvents" resultMap="eventResultMap">
SELECT
id,
e_name,
e_times,
e_level
FROM event
WHERE id=#{id}
<if test="level == 'A'">
AND e_times>10
</if>
</select>
這種寫法會(huì)報(bào)錯(cuò),因?yàn)橄?#39;A'這種單個(gè)字符的情況會(huì)被判定為字符,所以MyBatis認(rèn)為字符串在與字符做比較,從而報(bào)錯(cuò)。但是如果是'AA'或者'A'.toString() 這種,就會(huì)被判定為字符串,就正常。
二. if標(biāo)簽判斷數(shù)字
查詢參數(shù)Param如下。
public class Param {
private int id;
private String level;
private int times;
private String timestamp;
// 省略get和set
}
語句如下。
<select id="queryEvents3" resultMap="eventResultMap">
SELECT
id,
e_name,
e_times,
e_level
FROM event
WHERE e_level=#{level}
<if test="times != null">
AND e_times>#{times}
</if>
</select>
通過<if>標(biāo)簽也可以對數(shù)字判空,同時(shí)<if>標(biāo)簽也可以判斷數(shù)字的值,這里有多種寫法,下面給出正確寫法,推薦寫法和錯(cuò)誤寫法。
正確寫法1
<select id="queryEvents2" resultMap="eventResultMap">
SELECT
id,
e_name,
e_times,
e_level
FROM event
WHERE e_level=#{level}
<if test="times > '10'">
AND e_times>#{times}
</if>
</select>
注意''單引號中一定需要是多個(gè)數(shù)字。
正確寫法2
<select id="queryEvents2" resultMap="eventResultMap">
SELECT
id,
e_name,
e_times,
e_level
FROM event
WHERE e_level=#{level}
<if test="times > '0'.toString()">
AND e_times>#{times}
</if>
</select>
這種寫法不限制''單引號中的數(shù)字個(gè)數(shù),一個(gè)或多個(gè)都可以。
正確寫法3
<select id="queryEvents" resultMap="eventResultMap">
SELECT
id,
e_name,
e_times,
e_level
FROM event
WHERE e_level=#{level}
<if test="times > 0">
AND e_times>#{times}
</if>
</select>
判斷條件可以直接寫數(shù)字。
推薦寫法
<select id="queryEvents2" resultMap="eventResultMap">
SELECT
id,
e_name,
e_times,
e_level
FROM event
WHERE e_level=#{level}
<if test='times > "0"'>
AND e_times>#{times}
</if>
</select>
推薦外層用單引號,內(nèi)層用雙引號的寫法,能少踩很多坑。
錯(cuò)誤寫法
<select id="queryEvents" resultMap="eventResultMap">
SELECT
id,
e_name,
e_times,
e_level
FROM event
WHERE e_level=#{level}
<if test="times > '0'">
AND e_times>#{times}
</if>
</select>
'0'這種單個(gè)數(shù)字會(huì)被判定為字符,而字符'0'的ASCII值是48,所以times為49及以上時(shí),才滿足times > '0',所以這里有坑,切記。
總結(jié)
<if>標(biāo)簽的test判斷中,外層用雙引號,內(nèi)層用單引號時(shí),有如下比較規(guī)則。
- 允許數(shù)字與字符串做比較;
- 允許數(shù)字與字符做比較,但不推薦。數(shù)字與字符做比較時(shí),數(shù)字會(huì)與字符的ASCAII值做比較,容易出錯(cuò);
- 不允許包含字母的字符串與字符做比較。這種情況MyBatis會(huì)直接報(bào)錯(cuò);
- 允許全是數(shù)字的字符串與字符做比較,但不推薦。這種情況全是數(shù)字的字符串會(huì)作為數(shù)字來與字符的ASCII值來做比較,容易出錯(cuò)。
而在OGNL表達(dá)式中,如果單引號''中只有一個(gè)數(shù)字或者字母,那么就會(huì)被解析為字符,這時(shí)就會(huì)導(dǎo)致MyBatis或者比較結(jié)果錯(cuò)誤。
因此推薦<if>標(biāo)簽的test判斷中,外層用單引號,內(nèi)層用雙引號,能夠避免踩坑。
以上就是MyBatis動(dòng)態(tài)<if>標(biāo)簽使用避坑指南的詳細(xì)內(nèi)容,更多關(guān)于MyBatis動(dòng)態(tài)<if>標(biāo)簽的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Mybatis動(dòng)態(tài)SQL?foreach批量操作方法
這篇文章主要介紹了Mybatis動(dòng)態(tài)SQL?foreach批量操作方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
Spring Bean Scope 有狀態(tài)的Bean與無狀態(tài)的Bean
這篇文章主要介紹了Spring Bean Scope 有狀態(tài)的Bean與無狀態(tài)的Bean,每個(gè)用戶有自己特有的一個(gè)實(shí)例,在用戶的生存期內(nèi),bean保持了用戶的信息,下面來了解有狀態(tài)和無狀態(tài)的區(qū)別吧2022-01-01
Java數(shù)據(jù)結(jié)構(gòu)之圖的基礎(chǔ)概念和數(shù)據(jù)模型詳解
在現(xiàn)實(shí)生活中,有許多應(yīng)用場景會(huì)包含很多點(diǎn)以及點(diǎn)點(diǎn)之間的連接,而這些應(yīng)用場景我們都可以用即將要學(xué)習(xí)的圖這種數(shù)據(jù)結(jié)構(gòu)去解決。本文主要介紹了圖的基礎(chǔ)概念和數(shù)據(jù)模型,感興趣的可以了解一下2022-11-11
Java使用Runnable接口創(chuàng)建線程的示例代碼
在Java中,多線程編程是實(shí)現(xiàn)并發(fā)操作的重要手段之一,通過多線程,程序可以同時(shí)執(zhí)行多個(gè)任務(wù),從而提高應(yīng)用程序的效率和響應(yīng)速度,Java提供了多種創(chuàng)建線程的方式,其中實(shí)現(xiàn)Runnable接口是最常見且推薦的方式之一,本文將詳細(xì)介紹如何使用Runnable接口創(chuàng)建線程2025-02-02
java進(jìn)制轉(zhuǎn)換工具類實(shí)現(xiàn)減少參數(shù)長度
這篇文章主要為大家介紹了java進(jìn)制轉(zhuǎn)換工具類實(shí)現(xiàn)減少參數(shù)長度示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
springboot升級到j(luò)dk21最新教程(2023年)
你還在使用jdk8?快來看看最新出爐的SpringBoot+jdk21如何使用,下面這篇文章主要給大家介紹了關(guān)于springboot升級到j(luò)dk21的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10
Map集合中獲取key-value值的實(shí)現(xiàn)方法
這篇文章主要介紹了Map集合中獲取key-value值的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
九個(gè)動(dòng)畫組圖輪播總結(jié)全棧數(shù)據(jù)結(jié)構(gòu)數(shù)組鏈表
數(shù)據(jù)結(jié)構(gòu)和算法是密不可分的,兩者往往是相輔相成的存在,所以在學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)過程中,不免會(huì)遇到各種算法,數(shù)據(jù)結(jié)構(gòu)常用操作一般為:增刪改查?;旧纤械臄?shù)據(jù)結(jié)構(gòu)都是圍繞這幾個(gè)操作進(jìn)行展開,本文用九張動(dòng)圖來闡述先進(jìn)后出的數(shù)據(jù)結(jié)構(gòu)2021-08-08
Java使用@Retryable注解實(shí)現(xiàn)HTTP請求重試
HTTP調(diào)用是Java應(yīng)用與外部API進(jìn)行交互時(shí)重要的訪問方式之一,為了確保在遇到臨時(shí)性問題時(shí)能自動(dòng)重試,我們可以設(shè)計(jì)一個(gè)靈活的重試機(jī)制,在Java中,我們可以通過注解來實(shí)現(xiàn)這一功能,文將介紹如何使用注解@Retryable來實(shí)現(xiàn)HTTP調(diào)用的重試機(jī)制,需要的朋友可以參考下2024-10-10
Maven的pom.xml文件結(jié)構(gòu)中的build
本文主要介紹了Maven的pom.xml文件結(jié)構(gòu)中的build,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07

