Mybatis类型为Double时参数为0,if test !=''判断为false

    工作中遇到一个mybatis的问题,当实体类中数据类型为Double的字段传入参数为0时,查询或更新未生效。代码如下:

<result property="billMoney" column="bill_money" javaType="java.lang.Double" jdbcType="NUMERIC"/>

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

    在网上查了相关资料,大部分是说mybatis把0认为是空字符串了,所以当传入字段值为0的时候,if test判断为false,所以sql未能执行,导致更改或查询未生效。

    一般解决方案有下面两个:

方案1.去掉空字符串:

<if test="billMoney != null">
    and bill_money = #{billMoney}
</if>

方案2.增加对0的判断:

<if test="billMoney != null and billMoney !='' or billMoney == 0 ">
    and bill_money = #{billMoney}
</if>

    这两种方式都可以解决问题,最终实现的效果也是一样的,方案1相对来说代码更为简洁一些。

    解决问题看到这儿就够了,想知其所以然的小伙伴可以继续向下看。那为什么会出现这个问题呢,就必须去查看mybatis的源码实现了。

    我们通过debug进入mybatis代码层,首先进入的是MapperProxy类,调用了invoke()方法来对应mapper里的方法。接着调用了getResulSets类的getBoundSql()方法,来获取具体的执行sql。在MixedSqlNode类中进行sql的拼接。

  @Override
  public boolean apply(DynamicContext context) {
    for (SqlNode sqlNode : contents) {
      sqlNode.apply(context);
    }
    return true;
  }

    一步步追踪下去,sqlNode是否要拼接到执行sql上,最终是通过OgnlOps类的equal()方法来判断的,这也是我们研究的重点

public static boolean equal(Object v1, Object v2) {
    if (v1 == null) {
        return v2 == null;
    } 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;
    }
}

    这个方法是用来判断<if test="billMoney != null and billMoney !=''">and bill_money = #{billMoney}</if>最终的布尔值的,此时传入值为0.0,当比较值为null的时候,billMoney != null是返回了true,而billMoney !=''最终返回了false,也就是说在这次判断中,最终认为0.0是等于''的!那么为什么会出现这种情况呢,其实是经过一系列的方法调用,最后达成这个结果的。大致过程是equal()->isEqual()->compareWithConversion()->doubleValue()。由于都是存在于OgnlOps类中,这里我标出了两步关键代码。

      

 

 

    当字段类型为Double时,最终会走到case8这步判断,而在doubleValue()方法中,会将空字符串''解析为0.0。导致isEqual()方法最终返回的结果是true,进一步equal()结果返回ture,这也是0.0 !=''最终返回false的原因。

    当然,可以看出,mybatis并不是把传入的0.0解析成了空字符串,而是把mapper.xml里的空字符串解析成了0.0。

 

    扩展:都有哪些数据类型,最终会走到case8?

    先把结论写上,后续有时间再补充详细内容。8种基本类型以及包装类型,再加上BigInteger和BigDecimal,最终都会走到case8,这些类型都不能使用0!=''这样的判断。

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值