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">在有的時候也是一種曲線救國。

相關文章


感謝您閱讀【沉默王二的博客】,假設王二的博客給您帶來一絲幫助或感動。我(也就是王二)將不甚榮幸。
假設您碰巧喜歡。能夠留言或者私信我,這將是我鼓搗很多其它優秀文章的最強動力。


免責聲明!

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



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