mybatis 空字符串和0


最近在使用Mybatis的過程中遇到了一個奇怪的問題,如下所示:查詢SQL中的一個狀態條件,在param.sendstate=0或10時,單獨處理. 

<choose>
    <when test="param.sendstate!=null and param.sendstate == 10">
        and (SendState = 2 and (RESPONSETYPETEXT is null or RESPONSETYPETEXT =''))
    </when>
    <when test="param.sendstate!=null and param.sendstate == 0">
        and (SendState = 0 or SendState = '' or SendState is null)
    </when>
    <otherwise>
        <if test="param.sendstate!=null and param.sendstate!=''">
            and SendState = #{param.sendstate}
        </if>
    </otherwise>
</choose>

但是,當param.sendstate為空字符串時,通過控制台打印的SQL發現執行的SQL是:

也就是說此時 param.sendstate == 0結果是true

這個問題困擾了我半天,最后改成如下形式解決

<if test="param.state!=null and param.state!=''">
    <choose>
        <when test="param.state == 10">
            and (state = 10 and responsetext is null)
        </when>
        <when test="param.state == 0">
            and (state = 0 or state is null)
        </when>
        <otherwise>
            and state = #{param.state}
        </otherwise>
    </choose>
</if>

由於時間緊急,沒有深入去研究這個問題.后來看到了這篇文章

Mybatis參數Integer類型值為0 源碼處理

http://www.cnblogs.com/gushen-super/archive/2018/06/28/9238161.html

簡單跟蹤了下代碼,明白了問題在哪.

Mybatis在處理 if 標簽時,使用OGNL表達式處理並返回表達式的結果.

條件:param.sendstate == 0,此時param.sendstate是空字符串

OGNL在處理 == 運算時,最終調用的是 OgnlOps類的compareWithConversion方法

public static int compareWithConversion(Object v1, Object v2) {
        int result;
        if (v1 == v2) {
            result = 0;
        } else {
            int t1 = getNumericType(v1);
            int t2 = getNumericType(v2);
            int type = getNumericType(t1, t2, true);
            switch(type) {
            case 6:
                result = bigIntValue(v1).compareTo(bigIntValue(v2));
                break;
            case 9:
                result = bigDecValue(v1).compareTo(bigDecValue(v2));
                break;
            case 10:
                if (t1 == 10 && t2 == 10) {
                    if (v1 instanceof Comparable && v1.getClass().isAssignableFrom(v2.getClass())) {
                        result = ((Comparable)v1).compareTo(v2);
                        break;
                    }

                    throw new IllegalArgumentException("invalid comparison: " + v1.getClass().getName() + " and " + v2.getClass().getName());
                }
            case 7:
            case 8:
                double dv1 = doubleValue(v1);
                double dv2 = doubleValue(v2);
                return dv1 == dv2 ? 0 : (dv1 < dv2 ? -1 : 1);
            default:
                long lv1 = longValue(v1);
                long lv2 = longValue(v2);
                return lv1 == lv2 ? 0 : (lv1 < lv2 ? -1 : 1);
            }
        }

        return result;
    }

compareWithConversion方法有兩個Object類型的參數v1和v2,帶入上面的條件,即

  v1 = param.sendstate(空字符串)

  v2 = 0

經過getNumericType方法的處理,最終進入case=8里面處理,doubleValue方法如下:

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);
            }
        }
    }

可以看到,當value = 0 的時候,結果值為0.0,當value為空字符串時,結果值為0.0D

所以dv1 == dv2 結果為true,compareWithConversion方法的最終返回值為0,即相等. 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM