基于mybatis中test條件中單引號雙引號的問題
test條件中單引號雙引號問題
在mybatis中test判斷條件中使用單引號會報錯 通常使用雙引號
通常test后的判斷條件寫在雙引號內(nèi),但是當(dāng)條件中判斷使用字符串時應(yīng)該如下方式開發(fā)
<when ?test=“channel ==null” > <when ?test='channel =="QT"' >
具體原因
為單引號會被mybatis默認(rèn)為字符類型,若為單字符可以使用單引號。否則會報錯。
動態(tài)sql中test的一些問題
mybatis動態(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>
測試案例:
@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時返回的是country_id=2的結(jié)果
測試結(jié)果:
{"countryId":3,"country":"American Samoa","lastUpdate":"2006-02-15 04:44:00.0"}
居然返回的是country_id=3的結(jié)果
百度了才知道
原來傳值進(jìn)去的是String類型,而mybatis的動態(tài)sql中的OGNL表達(dá)式不會將單引號包裹的char類型的內(nèi)容轉(zhuǎn)成String類型,并且String類型和char類型直接比較一定是不相等的。所以輸出是country_id=3的結(jié)果
解決方案
將<when test="type == '0'">換成<when test='type == "0"'>即可,即將單引號換成雙引號
0==’'問題
一個更有趣的問題,如果將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>
測試案例不變:
@Test
public void getByTypeTest() throws JsonProcessingException {
? ? //此時傳值已經(jīng)沒有影響了
? ? String type = "0";
? ? CountryDo countryDo = countryManager.getByType(type);
? ? ObjectMapper mapper = new ObjectMapper();
? ? String json = mapper.writeValueAsString(countryDo);
? ? System.out.println(json);
}測試結(jié)果為:
{"countryId":2,"country":"Algeria","lastUpdate":"2006-02-15 04:44:00.0"}
怎么還是country_id=2的結(jié)果?,難道0==''??
查看mybatis源碼發(fā)現(xiàn),比如對于動態(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時,因?yàn)?是Number類型,所以被轉(zhuǎn)成了BigDecimal類型,并與0作比較,test的結(jié)果為true,所以返回的是country_id=2的結(jié)果,這個說法有誤。。。
再次調(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);
? ? }坑坑坑!!!
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
java的Array,List和byte[],String相互轉(zhuǎn)換的方法你了解嘛
這篇文章主要為大家詳細(xì)介紹了java的Array,List和byte[],String相互轉(zhuǎn)換的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-02-02
Spring Security 表單登錄功能的實(shí)現(xiàn)方法
這篇文章主要介紹了Spring Security 表單登錄,本文將構(gòu)建在之前簡單的 Spring MVC示例 之上,因?yàn)檫@是設(shè)置Web應(yīng)用程序和登錄機(jī)制的必不可少的。需要的朋友可以參考下2019-06-06
mybatis中關(guān)于mapper的使用以及注意事項
這篇文章主要介紹了mybatis中關(guān)于mapper的使用以及注意事項,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06
Struts2學(xué)習(xí)筆記(5)-參數(shù)傳遞方法
本文主要介紹Struts2中參數(shù)傳遞方法,希望能給大家做一個參考。2016-06-06

