mybatis空字符串和0相比为true

探讨MyBatis中对Integer类型0的误判问题,解析源码揭示空字符串与0被视为相等的原因,提出解决方案避免潜在错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题

<if test="field!=null and field!=''">
	and field=#{field}
</if>

mybatis中经常会用这种写法,这种写法一般都说,field是String类型.如果field在接口层是一个Integer(之所以是Integer,是历史代码不规范),并且是0的话,这个if条件是true 还是 false呢?
咋一看,感觉应该是true,因为0!=null && 0!=’’,但是实际上这个是false.这个场景下,mybatis认为空字符串和0是相等.这个结论很难以相信,是mybatis刻意为之,还是代码的bug?debug了下mybatis源码,找到了问题根源:

源码

mybatis源码->org.apache.ibatis.ognl.ASTEq->getValueBody->OgnlOps.equal(v1, v2)->OgnlOps.isEqual->compareWithConversion

result = compareWithConversion(object1, object2, true) == 0 || object1.equals(object2)

// compareWithConversion方法通过如下代码去比较
case 8:
double dv1 = doubleValue(v1);
double 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.0D;
        } else {
            Class c = value.getClass();
            if (c.getSuperclass() == Number.class) {
                return ((Number)value).doubleValue();
            } else if (c == Boolean.class) {
                return (double)((Boolean)value ? 1 : 0);
            } else if (c == Character.class) {
                return (double)(Character)value;
            } else {
            	// Integer的话,会走这个elase分支
                String s = stringValue(value, true);
                // 空字符串的长度是0,所以空字符串被转换成0.0D
                return s.length() == 0 ? 0.0D : Double.parseDouble(s);
            }
        }
    }

结论

关键在于 return s.length() == 0 ? 0.0D : Double.parseDouble(s); 这行代码,空字符串被转成了0.0D,0也被转成了0.0D,导致( 0 == ‘’ )为true.

1.对于Integer类型的字段如果加上field!=’'的判断,会不知不觉的导致0判断失败,导致field字段无法参与where过滤;
2.如果field是insert的字段,if判断失败,会导致field==0的时候,field字段无法插入。

解决办法:

1.将field字段改为String类型
2.去掉field!=’‘的判断,值得注意的是,现在主流的自动生成mybatis的工具,都会对Integer字段加上这个field!=’'的判断

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值