日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【MyBatis使用】mapper.xml 文件内<if test>标签判断参数值不等于null和空 当参数值为 0 时筛选条件失效原因分析(源码探究)

發(fā)布時(shí)間:2024/10/6 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【MyBatis使用】mapper.xml 文件内<if test>标签判断参数值不等于null和空 当参数值为 0 时筛选条件失效原因分析(源码探究) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這個(gè)問(wèn)題有不少小伙伴遇到過(guò),也給出了解決方案,但是沒有探究原因,這次讀一下源碼,看看原因在哪里。

1. 條件失效情況復(fù)現(xiàn)

  • Mapper.xml內(nèi)的動(dòng)態(tài)SQL如下【偽代碼】
<select id="getInfoList" parameterType="java.util.Map" resultType="java.util.Map">SELECT*${schemaName}${tableName}<where><if test="viewId != null and viewId != ''">AND viewid = #{viewId}</if></where></select>
  • 調(diào)用動(dòng)態(tài)SQL的方法如下【偽代碼主要是顯示一下傳遞的參數(shù)值】
Map<String, Object> mapParam = new HashMap<>(4); mapParam.put("schemaName", "public"); mapParam.put("tableName", "info_table"); mapParam.put("viewId", 0); queryInterface.getInfoList(mapParam);

查看查詢結(jié)果會(huì)發(fā)現(xiàn)對(duì) viewId 沒有進(jìn)行篩選。

2. 解決方法

去掉判斷條件 and viewId != '' 即可。

<select id="getInfoList" parameterType="java.util.Map" resultType="java.util.Map">SELECT*${schemaName}${tableName}<where><if test="viewId != null">AND viewid = #{viewId}</if></where></select>

3. 源碼解析

到底是為什么呢?我們找到 Mybatis 的 IfSqlNode 對(duì)象:


下邊是打斷點(diǎn)進(jìn)行的參數(shù)追蹤:

evaluator.evaluateBoolean(test, context.getBindings()) 為 true 時(shí)當(dāng)前節(jié)點(diǎn)才會(huì)被應(yīng)用。

進(jìn)入 evaluateBoolean(test, context.getBindings()) 方法。

進(jìn)入 OgnlCache.getValue(expression, parameterObject) 方法。
關(guān)鍵方法出現(xiàn)了:Ognl.getValue(parseExpression(expression), context, root);

我們找到 Ognl.getValue(parseExpression(expression), context, root)方法。

中間省略了部分方法,省略的方法主要是查找參數(shù)名稱和參數(shù)值,不重要故未貼出。還有判斷節(jié)點(diǎn)類型的過(guò)程,例子中用的的都是不等于類型的節(jié)點(diǎn)。下邊的方法真正開始對(duì)表達(dá)式兩側(cè)的數(shù)值進(jìn)行比較了。前半段的 viewId != null 不再貼出,只截圖有問(wèn)題的后半段:


進(jìn)入最核心的方法比較方法 compareWithConversion(Object v1, Object v2)

看一下轉(zhuǎn)換的過(guò)程:

問(wèn)題的核心代碼:

public static double doubleValue(Object value) throws NumberFormatException {if (value == null) {return 0.0D;} else {Class c = value.getClass();if (c.getSuperclass() == Number.class) {return ((Number)value).doubleValue();} else if (c == Boolean.class) {return (Boolean)value ? 1.0D : 0.0D;} else if (c == Character.class) {return (double)(Character)value;} else {String s = stringValue(value, true);return s.length() == 0 ? 0.0D : Double.parseDouble(s);}}}

由于 "".length() = 0,傳遞的參數(shù) viewId 值是 0?? 時(shí) viewId != '' 就變成 0.0 != 0.0 這個(gè)自然是 false 此時(shí),篩選條件不起作用就不足為奇了。
為什么會(huì)出現(xiàn)這種情況?是框架問(wèn)題嗎? 感覺不是的,我們?cè)诰幊痰臅r(shí)候,對(duì)數(shù)值類型值的判斷本身就不應(yīng)該使用 =='' 或者 !=''這樣的條件。

總結(jié)

以上是生活随笔為你收集整理的【MyBatis使用】mapper.xml 文件内<if test>标签判断参数值不等于null和空 当参数值为 0 时筛选条件失效原因分析(源码探究)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。