MyBatis 數值類型 where 條件配置的坑


更多文章參考我的筆記:https://www.yuque.com/yinjianwei/vyrvkf

 

復現異常

我們先通過案例復現該類異常,測試項目地址:https://gitee.com/yin_jw/demo/tree/master/mybatis-demo/springboot-mybatis-demo,StudentMapper.xml 中根據條件獲取學生信息的 SQL 配置如下所示。

<!-- 根據條件獲取學生信息-->
<select id="listByConditions" parameterType="studentQuery" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from t_student
    <where>
        <if test="ids != null and ids.size() > 0">
            AND id IN
            <foreach collection="ids" item="item" open="(" close=")" separator=",">
                #{item}
            </foreach>
        </if>
        <if test="name != null and name != ''">
            AND name LIKE CONCAT('%', #{name}, '%')
        </if>
        <if test="sex != null and sex != ''">
            AND sex = #{sex}
        </if>
        <if test="selfcardNo != null">
            AND selfcard_no = #{selfcardNo}
        </if>
    </where>
</select>

該配置問題出在 <if test="sex != null and sex != ''"> 這段代碼,sex 在傳入的參數中是 Byte 類型,屬於數值類型,而 sex != '' 適用於字符串類型判斷,我們誤將數值類型當成字符串類型配置了。

當我們錯誤的配置了 sex 字段的判斷條件,傳入 sex = 0 時,sex != '' 會返回 false,傳入 sex = 1 時,sex != '' 會返回 true,同樣是傳入數字,為什么會出現兩種不同的結果呢? 

sex = 0 的執行效果如下圖所示:

sex = 1 的執行效果如下圖所示:

sex = 0 的執行返回內容明顯不是我們需要的結果,下面我們通過源碼分析來解開這個謎題。

分析源碼 

通過源碼分析篇中的“MyBatis 源碼篇-SQL 執行的流程”章節,我們知道 MyBatis 執行 SQL 最終都會交給 Executor 類執行。 

前面的調試步驟省略,直接進入 CacheExecutor 類的 query 方法。

猜測 MyBatis 根據參數和映射配置文件生成 boundSql 的時候,出現了一些問題。我們一路往下 DEBUG,發現問題出在 MyBatis 對 OGNL 表達式處理上面。 

org.apache.ibatis.ognl.OgnlOps#compareWithConversion(Object v1, Object v2) 該方法在比較 (Byte)0 和 "" 時,返回的是 true,也就是該方法認為兩者是相同的,執行結果如下圖所示。

所以,sex = 0 的條件沒有出現在生成的 SQL 中。

那么當 sex = 1 的時候,compareWithConversion(Object v1, Object v2) 方法的執行結果是怎樣的呢?

修改參數,調試測試接口,執行結果如下圖所示:

compareWithConversion(Object v1, Object v2) 方法返回的結果是 false,其實該問題的本質是,org.apache.ibatis.ognl.OgnlOps#doubleValue(Object value) 方法當 value 是空字符串時返回 0.0D。

結論 

對於數值類型的參數,在配置 where 條件的時候要注意,不能把它當成字符串類型判斷,數值型只需要判斷 sex != null 就可以了。


免責聲明!

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



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