Mybatis+0+null,小問題引起的血案

Mybatis在進行<if test="status != null and status != ''">判空操做時,若是status爲0的時候,該判斷條件的值爲false,也就是說Mybatis此時把0做爲null來進行判斷的,因此遇到這種狀況時,只能按照下面這個方法來辦!java

1、源碼調查結果

遇到這個問題時,我翻看了Mybatis的源碼,發現其在ExpressionEvaluator.java類的evaluateBoolean方法處返回了false,這個源碼包的分析方式和源碼分析 There is no getter for property named ‘*’ in ‘class java.lang.String有極大的相同之處。sql

但發現了問題,也然並卵,修改Mybatis的源碼我是不行,因此只能曲線救國!數據庫

2、場景分析

數據庫字段mybatis

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

此時0表示未支付,1表示支付,那麼按照通常的邏輯來看,查詢語句須要寫成這樣的形式:源碼分析

select * from ym_deals y WHERE d.deal_id = 1

        <if test="status != null and status != ''">
    and y.status = #{status}
</if>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

其意義在於,當查詢參數不傳遞未支付或者支付條件時,就須要查詢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顯然是不符的!lua

也就是說,Mybatis自做主張的把status爲0的條件當作了if的false結果!spa

3、解決辦法

①、對傳遞參數攔截

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;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
vo.addParams("status", StrUtil.parseStringToInt(vo.getParams("status"), -1));
  • 1

也就是說在查詢全部支付狀態的訂單時,把status的值轉換爲-1..net

②、重構Mybatis的查詢語句

select * from ym_deals y WHERE d.deal_id = 1

        <if test="status != -1">
    and y.status = #{status}
</if>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

此時再也不判空,而判-1。code

按照以上的辦法就解決了問題,不知道你那是否有更好的解決辦法?blog

4、後記

這篇文章發表以後,有熱心的朋友給出下面的解決辦法:

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">在有的時候也是一種曲線救國。
相關文章
相關標籤/搜索