zoukankan      html  css  js  c++  java
  • Mybatis+0+null,小问题引发的血案

    Mybatis在进行<if test="status != null and status != ''">判空操作时,假设status为0的时候,该推断条件的值为false,也就是说Mybatis此时把0作为null来进行推断的,所以遇到这样的情况时。仅仅能依照以下这种方法来办!

    一、源代码调查结果

    遇到这个问题时。我翻看了Mybatis的源代码,发现其在ExpressionEvaluator.java类的evaluateBoolean方法处返回了false,这个源代码包的分析方式和源代码分析 There is no getter for property named ‘*’ in ‘class java.lang.String有极大的同样之处。

    但发现了问题。也然并卵,改动Mybatis的源代码我是不行,所以仅仅能曲线救国!

    二、场景分析

    数据库字段

      `status` tinyint(2) NOT NULL COMMENT '0未支付,1已支付',

    此时0表示未支付,1表示支付。那么依照一般的逻辑来看。查询语句须要写成这样的形式:

    select * from ym_deals y WHERE d.deal_id = 1
    
            <if test="status != null and status != ''">
        and y.status = #{status}
    </if>
    

    其意义在于。当查询參数不传递未支付或者支付条件时。就须要查询status为0和1的所有结果。也就是说没有条件and y.status = #{status}。但事实就纠结了,当status传递的參数为1时,if条件的结果为true,也就是说sql语句变成了select * from ym_deals y WHERE d.deal_id = 1 and y.status=1,查询结果正常,但假设status为0此时,sql语句变成了select * from ym_deals y WHERE d.deal_id = 1,与预期结果select * from ym_deals y WHERE d.deal_id = 1 and y.status=0显然是不符的!

    也就是说,Mybatis自作主张的把status为0的条件当做了if的false结果!

    三、解决的方法

    ①、对传递參数拦截

        public static int parseStringToInt(Object parameter, int defualtValue) {
            try {
                if ((parameter == null) || (parameter.equals(""))) {
                    return defualtValue;
                }
                return Integer.parseInt(parameter.toString());
            } catch (Exception ex) {
            }
            return 0;
        }
    vo.addParams("status", StrUtil.parseStringToInt(vo.getParams("status"), -1));

    也就是说在查询所有支付状态的订单时,把status的值转换为-1.

    ②、重构Mybatis的查询语句

    select * from ym_deals y WHERE d.deal_id = 1
    
            <if test="status != -1">
        and y.status = #{status}
    </if>
    

    此时不再判空,而判-1。

    依照以上的办法就攻克了问题。不知道你那是否有更好的解决的方法?


    四、后记

    这篇文章发表之后,有热心的朋友给出以下的解决的方法:

    lengjian68 status是Integer 类型的 把status!=‘’ 给去掉
    去掉就好了

    1楼 qq_30159115 确定是 int类型的就不用 推断 status != ‘’ 就搞定了

    Re: Optimistic_ 发表 回复qq_30159115:给力啊。感谢!
    推断不是为空。对于int类型就是在推断不为0么?

    依照朋友给出的观点。我尝试了一下,结果如朋友所说。status确定为integer类型的,把status!=”给去掉就好了。

    那么如今又一次来看,我本来的做法就有问题,integer类型的,我干嘛要用status!=”来进行推断,这显然是一种不负责任的做法,至于<if test="status != null and status != ''">的推断条件。显然是错误的,从原则上来讲,该推断条件仅仅能来推断status为string类型的,用来推断integer类型。岂不贻笑慷慨,至于后面我提出的解决方式,显然也就无力苍白。我仅仅想把这篇文章立刻删掉,好不再误导他人。

    但看到

    Re: Optimistic_ 发表 回复qq_30159115:给力啊!感谢!


    推断不是为空,对于int类型就是在推断不为0么?

    以下这位朋友的疑问,我认为,这篇文章存在另一些价值,由于还有和我一样的朋友在犯错。“推断不是为空,对于int类型就是在推断不为0么?”这样的认识显然是第二种错误,integer类型非常明显存在为null的情况,那么对于int类型当然不是在推断为0的。(当然了。这位仁兄说int类型,在严格意义上讲。就不存在null的可能了,那么我仅仅能武断的猜測任务。这位朋友是在说integer,请原谅我的鲁莽)

    那么得出下面结论:

    1. <if test="status != null">中status为integer类型的。status=0的推断结果为true。
    2. <if test="status != null and status != ''">中status为integer类型的,status=0的推断结果为false。mybatis把status作为了string来进行推断。

    3. 假设status为integer,提前对status进行去空操作,再推断<if test="status != -1">在有的时候也是一种曲线救国。

    相关文章


    感谢您阅读【沉默王二的博客】,假设王二的博客给您带来一丝帮助或感动。我(也就是王二)将不甚荣幸。
    假设您碰巧喜欢。能够留言或者私信我,这将是我鼓捣很多其它优秀文章的最强动力。

  • 相关阅读:
    数据中台实战(六):交易分析
    数据中台实战(五):自助分析平台(产品设计篇)
    数据中台实战(四):商品分析(产品设计篇)
    数据中台实战(三):用户分析(产品设计篇)
    数据中台实战(二):基于阿里OneData的数据指标管理体系
    数据中台实战(一):以B2B电商亿订为例,谈谈产品经理视角下的数据埋点
    LeetCode82. 删除排序链表中的重复元素 II
    LeetCode203. 移除链表元素
    LeetCode445. 两数相加 II
    LeetCode2. 两数相加
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/7106568.html
Copyright © 2011-2022 走看看