Mybatis if标签test中 空字符串与0相等的问题

目录

 

场景

查看mybatis执行代码

修改


场景

拨打频次,前端不筛选时,传参:"",需要过滤出0的情况时,传参:0;但过滤0的情况时,还是出现了全量数据。

代码:

<if test="data.callFrequency != null and data.callFrequency != ''">
    ...
</if>

查看mybatis执行代码

class ASTNotEq extends ComparisonExpression {
    public ASTNotEq(int id) {
        super(id);
    }

    public ASTNotEq(OgnlParser p, int id) {
        super(p, id);
    }

    protected Object getValueBody(OgnlContext context, Object source) throws OgnlException {
        //传参值,也就是0
        Object v1 = this._children[0].getValue(context, source);
        //test中条件的值,也就是''
        Object v2 = this._children[1].getValue(context, source);
        // 去比较两值
        return OgnlOps.equal(v1, v2) ? Boolean.FALSE : Boolean.TRUE;
    }
}

获取到v1 = 0,v2 = ''  去比较

查看比较逻辑

    public static boolean equal(Object v1, Object v2) {
        if (v1 == null) {
            return v2 == null;
        // 走到isEqual方法
        } else if (v1 != v2 && !isEqual(v1, v2)) {
            if (v1 instanceof Number && v2 instanceof Number) {
                return ((Number)v1).doubleValue() == ((Number)v2).doubleValue();
            } else {
                return false;
            }
        } else {
            return true;
        }
    }


    public static boolean isEqual(Object object1, Object object2) {
        boolean result = false;
        if (object1 == object2) {
            result = true;
        } else if (object1 != null && object1.getClass().isArray()) {
            if (object2 != null && object2.getClass().isArray() && object2.getClass() == object1.getClass()) {
                result = Array.getLength(object1) == Array.getLength(object2);
                if (result) {
                    int i = 0;

                    for(int icount = Array.getLength(object1); result && i < icount; ++i) {
                        result = isEqual(Array.get(object1, i), Array.get(object2, i));
                    }
                }
            }
        } else {
            // 进入到compareWithConversion方法
            result = object1 != null && object2 != null && (object1.equals(object2) || compareWithConversion(object1, object2) == 0);
        }

        return result;
    }


    public static int compareWithConversion(Object v1, Object v2) {
        int result;
        if (v1 == v2) {
            result = 0;
        } else {
            // 获取到v1,v2类型的对应值
            int t1 = getNumericType(v1); // 4
            int t2 = getNumericType(v2); // 10
            int type = getNumericType(t1, t2, true);// 10
            switch(type) {
            case 6:
                result = bigIntValue(v1).compareTo(bigIntValue(v2));
                break;
            case 9:
                result = bigDecValue(v1).compareTo(bigDecValue(v2));
                break;
            case 10:
                // t1 != t2
                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 0.0
                double dv1 = doubleValue(v1);
                double dv2 = doubleValue(v2);
                // 返回true,'' == 0
                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;
    }


    public static int getNumericType(Object value) {
        if (value != null) {
            Class c = value.getClass();
            if (c == Integer.class) {
                return 4;
            }

            if (c == Double.class) {
                return 8;
            }

            if (c == Boolean.class) {
                return 0;
            }

            if (c == Byte.class) {
                return 1;
            }

            if (c == Character.class) {
                return 2;
            }

            if (c == Short.class) {
                return 3;
            }

            if (c == Long.class) {
                return 5;
            }

            if (c == Float.class) {
                return 7;
            }

            if (c == BigInteger.class) {
                return 6;
            }

            if (c == BigDecimal.class) {
                return 9;
            }
        }

        return 10;
    }

 getNumericType获取到v1,v2的类型对应值,如下图

通过getNumericType(t1, t2, true)方法获取type

    public static int getNumericType(int t1, int t2, boolean canBeNonNumeric) {
        if (t1 == t2) {
            return t1;
        } else if (canBeNonNumeric && (t1 == 10 || t2 == 10 || t1 == 2 || t2 == 2)) {
            // v2 = 10, 返回10
            return 10;
        } else {
            if (t1 == 10) {
                t1 = 8;
            }

            if (t2 == 10) {
                t2 = 8;
            }

            if (t1 >= 7) {
                if (t2 >= 7) {
                    return Math.max(t1, t2);
                } else if (t2 < 4) {
                    return t1;
                } else {
                    return t2 == 6 ? 9 : Math.max(8, t1);
                }
            } else if (t2 >= 7) {
                if (t1 < 4) {
                    return t2;
                } else {
                    return t1 == 6 ? 9 : Math.max(8, t2);
                }
            } else {
                return Math.max(t1, t2);
            }
        }
    }

由于v1 != v2,所以跳到case 8,如下,返回true

最终,返回true,传参为0被条件 data.callFrequency != '' 过滤掉,所以不会走拨打频次筛选。

修改

修改test筛选如下:

<if test="data.callFrequency != null and data.callFrequency != '' or data.callFrequency == 0">
    ...
</if>

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值