基于mybatis中test條件中單引號(hào)雙引號(hào)的問題
test條件中單引號(hào)雙引號(hào)問題
在mybatis中test判斷條件中使用單引號(hào)會(huì)報(bào)錯(cuò) 通常使用雙引號(hào)
通常test后的判斷條件寫在雙引號(hào)內(nèi),但是當(dāng)條件中判斷使用字符串時(shí)應(yīng)該如下方式開發(fā)
<when ?test=“channel ==null” > <when ?test='channel =="QT"' >
具體原因
為單引號(hào)會(huì)被mybatis默認(rèn)為字符類型,若為單字符可以使用單引號(hào)。否則會(huì)報(bào)錯(cuò)。
動(dòng)態(tài)sql中test的一些問題
mybatis動(dòng)態(tài)sql中OGNL中type=="1"和type='1'的區(qū)別
最近在mybatis中使用OGNL所遇到的坑: 一點(diǎn)雞肋: type=="1"和type='1'的區(qū)別
//CountryDao.java
public interface CountryDao {
? ? CountryDo getByType(@Param("type") String type);
}
//CountryManager.java
@Component("countryManager")
public class CountryManager {
? ? @Autowired
? ? private CountryDao countryDao;
? ? public CountryDo getByType(String type){
? ? ? ? return countryDao.getByType(type);
? ? }
}mapper.xml:
//.xml <select id="getByType" resultType="com.github.**.domain.CountryDo"> ? ? <choose> ? ? ? //注意寫法`type=='0'` ? ? ? ? <when test="type == '0'"> ? ? ? ? ? ? SELECT * FROM country WHERE country_id = 2 ? ? ? ? </when> ? ? ? ? <otherwise> ? ? ? ? ? ? SELECT * FROM country WHERE country_id = 3; ? ? ? ? </otherwise> ? ? </choose> </select>
測(cè)試案例:
@Test
public void getByTypeTest() throws JsonProcessingException {
? ? String type = "0";
? ? CountryDo countryDo = countryManager.getByType(type);
? ? ObjectMapper mapper = new ObjectMapper();
? ? String json = mapper.writeValueAsString(countryDo);
? ? System.out.println(json);
}理想情況下,當(dāng)type=0時(shí)返回的是country_id=2的結(jié)果
測(cè)試結(jié)果:
{"countryId":3,"country":"American Samoa","lastUpdate":"2006-02-15 04:44:00.0"}
居然返回的是country_id=3的結(jié)果
百度了才知道
原來傳值進(jìn)去的是String類型,而mybatis的動(dòng)態(tài)sql中的OGNL表達(dá)式不會(huì)將單引號(hào)包裹的char類型的內(nèi)容轉(zhuǎn)成String類型,并且String類型和char類型直接比較一定是不相等的。所以輸出是country_id=3的結(jié)果
解決方案
將<when test="type == '0'">換成<when test='type == "0"'>即可,即將單引號(hào)換成雙引號(hào)
0==’'問題
一個(gè)更有趣的問題,如果將mapper.xml文件內(nèi)容換成:
<select id="getByType" resultType="com.github.sijing.domain.CountryDo"> ? ? <choose> ? ? ? ? <when test="0 ==''"> ? ? ? ? ? ? SELECT * FROM country WHERE country_id = 2 ? ? ? ? </when> ? ? ? ? <otherwise> ? ? ? ? ? ? SELECT * FROM country WHERE country_id = 3; ? ? ? ? </otherwise> ? ? </choose> </select>
測(cè)試案例不變:
@Test
public void getByTypeTest() throws JsonProcessingException {
? ? //此時(shí)傳值已經(jīng)沒有影響了
? ? String type = "0";
? ? CountryDo countryDo = countryManager.getByType(type);
? ? ObjectMapper mapper = new ObjectMapper();
? ? String json = mapper.writeValueAsString(countryDo);
? ? System.out.println(json);
}測(cè)試結(jié)果為:
{"countryId":2,"country":"Algeria","lastUpdate":"2006-02-15 04:44:00.0"}
怎么還是country_id=2的結(jié)果?,難道0==''??
查看mybatis源碼發(fā)現(xiàn),比如對(duì)于動(dòng)態(tài)sql<if>標(biāo)簽的解析:
// IfSqlNode.
@Override
?public boolean apply(DynamicContext context) {
? ?if (evaluator.evaluateBoolean(test, context.getBindings())) {
? ? ?contents.apply(context);
? ? ?return true;
? ?}
? ?return false;
?}在evaluator.evaluateBoolean方法中:
//ExpressionEvaluator.java OGNL表達(dá)式處理
public boolean evaluateBoolean(String expression, Object parameterObject) {
? Object value = OgnlCache.getValue(expression, parameterObject);
? if (value instanceof Boolean) {
? ? return (Boolean) value;
? }
? if (value instanceof Number) {
? ? return new BigDecimal(String.valueOf(value)).compareTo(BigDecimal.ZERO) != 0;
? }
? return value != null;
}當(dāng)傳入值為0時(shí),因?yàn)?是Number類型,所以被轉(zhuǎn)成了BigDecimal類型,并與0作比較,test的結(jié)果為true,所以返回的是country_id=2的結(jié)果,這個(gè)說法有誤。。。
再次調(diào)試,首先char ''被轉(zhuǎn)成了字符String"",大概在OgnlOps.java文件的isEqual方法中的(compareWithConversion(object1, object2) == 0),點(diǎn)進(jìn)去發(fā)現(xiàn):
case NONNUMERIC:
? ? if ((t1 == NONNUMERIC) && (t2 == NONNUMERIC)) {
? ? ? ? if ((v1 instanceof Comparable) && v1.getClass().isAssignableFrom(v2.getClass())) {
? ? ? ? ? ? result = ((Comparable) v1).compareTo(v2);
? ? ? ? ? ? break;
? ? ? ? } else {
? ? ? ? ? ? throw new IllegalArgumentException("invalid comparison: " + v1.getClass().getName() + " and "
? ? ? ? ? ? ? ? ? ? + v2.getClass().getName());
? ? ? ? }
? ? }
? ? // else fall through
case FLOAT:
case DOUBLE:
?? ?//v1=0, v2=""
? ? double dv1 = doubleValue(v1),
? ? dv2 = doubleValue(v2);
? ? return (dv1 == dv2) ? 0 : ((dv1 < dv2) ? -1 : 1);在doubleValue方法中:
public static double doubleValue(Object value)
? ? ? ? throws NumberFormatException
? ? {
? ? ? ? if (value == null) return 0.0;
? ? ? ? Class c = value.getClass();
? ? ? ? if (c.getSuperclass() == Number.class) return ((Number) value).doubleValue();
? ? ? ? if (c == Boolean.class) return ((Boolean) value).booleanValue() ? 1 : 0;
? ? ? ? if (c == Character.class) return ((Character) value).charValue();
? ? ? ? String s = stringValue(value, true);
? ? ? ? return (s.length() == 0) ? 0.0 : Double.parseDouble(s);
? ? }坑坑坑!!!
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
springboot 自定義404、500錯(cuò)誤提示頁面的實(shí)現(xiàn)
springboot 默認(rèn)已經(jīng)提供了一套處理異常的機(jī)制。在 springboot 中提供了一個(gè)名為 BasicErrorController 的類來處理 /error 請(qǐng)求,然后跳轉(zhuǎn)到默認(rèn)顯示異常的頁面來展示異常信息,本文就詳細(xì)的介紹一下,感興趣的可以了解一下2021-11-11
Java?properties?和?yml?的區(qū)別解析
properties和yml都是Spring?Boot支持的兩種配置文件,它們可以看做Spring?Boot在不同時(shí)期的兩種“產(chǎn)品”,這篇文章主要介紹了Java?properties?和?yml?的區(qū)別,需要的朋友可以參考下2023-02-02
java如何將一個(gè)float型數(shù)的整數(shù)部分和小數(shù)分別輸出顯示
這篇文章主要介紹了java如何將一個(gè)float型數(shù)的整數(shù)部分和小數(shù)分別輸出顯示,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
spring使用RedisTemplate操作Redis數(shù)據(jù)庫
這篇文章主要介紹了spring使用RedisTemplate操作Redis數(shù)據(jù)庫,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
Mybatis使用useGeneratedKeys獲取自增主鍵的方法
這篇文章主要給大家介紹了關(guān)于Mybatis使用useGeneratedKeys獲取自增主鍵的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Mybatis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
spring如何快速穩(wěn)定解決循環(huán)依賴問題
這篇文章主要介紹了spring如何快速穩(wěn)定解決循環(huán)依賴問題,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
Java concurrency之AtomicReference原子類_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
AtomicReference是作用是對(duì)"對(duì)象"進(jìn)行原子操作。這篇文章主要介紹了Java concurrency之AtomicReference原子類,需要的朋友可以參考下2017-06-06

