“原創(chuàng)精選,轉(zhuǎn)載注明出處,三克油”
前言
- Mbatis 的script標(biāo)簽可以支持很多動(dòng)態(tài)SQL查詢、在使用if test判斷的時(shí)候、會(huì)有一些意向不到的坑
正文
- 我們一般在Mbatis中做update更新時(shí)、都會(huì)加上使用if test判斷、防止更新空值、一般正常都是像name這種既判斷NULL又判斷''
- 但是對(duì)于int類型的sex字段、如果加上 sex != ''條件時(shí)、當(dāng)sex值為0時(shí)、此sql不會(huì)被拼加上、也不會(huì)被執(zhí)行更新
<if test="name !=null and name !='' ">
name = #{name},
</if>
<if test="sex !=null">
sex = #{sex},
</if>
- 以上是問題以及現(xiàn)象、現(xiàn)在讓我們來看一下Mbatis源碼、為什么會(huì)出現(xiàn)這種情況
- 首先在mbatis中找到啊以上包路徑、此路徑為解析script標(biāo)簽時(shí)用到的類
org.apache.ibatis.scripting
- 過程不在細(xì)說、對(duì)于mbatis來說、script標(biāo)簽的動(dòng)態(tài)SQL、都是遍歷條件做SQL拼接而成的
- 我們直接看org.apache.ibatis.scripting.xmltags.IfSqlNode這個(gè)類、此類是script標(biāo)簽中if標(biāo)簽的判斷方式、其中evaluateBoolean返回true時(shí)、if標(biāo)簽下的SQL拼接生效
public boolean apply(DynamicContext context) {
if (evaluator.evaluateBoolean(test, context.getBindings())) {
contents.apply(context);
return true;
}
return false;
}
- 再具體看org.apache.ibatis.scripting.xmltags.ExpressionEvaluator :evaluateBoolean 這個(gè)方法、我們看到了如果是number類型、會(huì)與0做判斷比較
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)).equals(BigDecimal.ZERO);
return value != null;
}
- 由此可以發(fā)現(xiàn)、當(dāng)動(dòng)態(tài)sql參數(shù)是int類型、并且傳入0時(shí)、是使用OgnlCache獲取的value、而OgnlCache是對(duì)OGNL的封裝
- 在OGNL的官網(wǎng)上面可以看到如下解釋
Any object can be used where a boolean is required. OGNL interprets objects as booleans like this:
· If the object is a Boolean, its value is extracted and returned;
· If the object is a Number, its double-precision floating-point value is compared with zero; non-zero is treated as true, zero as false;
· If the object is a Character, its boolean value is true if and only if its char value is non-zero;
Otherwise, its boolean value is true if and only if it is non-null.
結(jié)尾
For Future.