更多文章参考我的笔记: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 就可以了。

MyBatis 数值类型 where 条件配置的坑的更多相关文章

  1. 005 Python的数值类型

    005 Python的数值类型 BIF    指的是内置函数,一般不作为变量命名.如 input,while,if,else,float,等等.整型:整数.(python3.0版本把整型和长整型结合在 ...

  2. myBatis 基础测试 表关联关系配置 集合 测试

    myBatis 基础测试 表关联关系配置 集合 测试 测试myelipse项目源码 sql 下载 http://download.csdn.net/detail/liangrui1988/599388 ...

  3. mybatis sql中的条件语句

    1.mybatis判断是否为空或null <if test="type!=null and type!=''"> AND type = #{type} </if& ...

  4. mybatis generator的generatorConfig.xml配置详解

    generatorConfig.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ge ...

  5. 深入浅出Mybatis系列(四)---配置详解之typeAliases别名(mybatis源码篇)

    上篇文章<深入浅出Mybatis系列(三)---配置详解之properties与environments(mybatis源码篇)> 介绍了properties与environments, ...

  6. MySQL的数值类型,时间

    数值类型 整数型 tinyint  smallint  mediumint  int|integer  bigint 注意: 1, 如何选择数据类型,我们的原则是:够用就行!尽量的选择占用内存小的整型 ...

  7. MySQL数据类型——数值类型

    1.1.1 整型 整型 占用字节 范围 范围 tinyint 1 -27~27-1 -128~127 smallint 2 -215~215-1 -32768~32767 mediumint 3 -2 ...

  8. MyBatis Generator自动生成的配置及使用

    注意:文件名不能有中文字符,不然不能自动生成 找到MyBatis Generator.rar\MyBatis Generator\eclipse里的features和plugins文件,把这两个文件复 ...

  9. MySQL学习分享--数值类型

    数值类型 MySQL的数值类型包括整数类型.浮点数类型.定点数类型.位类型. 整数类型 MySQL支持的整数类型有tinyint.smallint.mediumint.int.bigint(范围从小到 ...

随机推荐

  1. Docker学习3-简单shell脚本安装mysql5.7与docker小技巧

    前言 玩过Windows中的 .bat 的小伙伴是不是觉得很有意思呢,github中一键推送.同步拉取等等操作,哈哈,当然shell脚本也是很类似,可以运行一个脚本就可以自动给我们部署好环境啦!但是这 ...

  2. JS单例对象与构造函数对象的区别

    JavaScript对象有几种: 内置对象如Global,Math对象等等. 本地对象如Object.Function.Array.String.Boolean.Number.Date.RegExp. ...

  3. 前端Vue框架-vuex状态管理详解

    新人报道!多多关照-多提宝贵意见 谢谢- vuex理解 采用集中式存储管理模式.用来管理组件的状态,并以自定义规则去观测实时监听值得变化. 状态模式管理理解 属性 理解 state 驱动应用的数据源 ...

  4. 2019.10.28 CSP%您赛第四场t3

    我写不动前两个了. 原谅一下. ____________________________________________________________________________________ ...

  5. volatile关键字使用

    1.volatile 使用场景(多线程情况下): 适合使用在 一写多读 的情况下: 2.volatile 理解分析: 使用 volatile 关键字修饰的变量,值在改变时会直接刷新到 主内存 中,而不 ...

  6. java秀发入门到优雅秃头路线导航【教学视频+博客+书籍整理】

    目录 一.Java基础 二.关于JavaWeb基础 三.关于数据库 四.关于ssm框架 五.关于数据结构与算法 六.关于开发工具idea 七.关于项目管理工具Mawen.Git.SVN.Gradle. ...

  7. 第三篇 Flask中的request

    每个框架中都有处理请求的机制(request),但是每个框架的处理方式和机制是不同的,下面我们来了解一下Flask的request中都有什么东西 from flask import request 1 ...

  8. Linux Capabilities 入门教程:基础实战篇

    该系列文章总共分为三篇: Linux Capabilities 入门教程:概念篇 Linux Capabilities 入门教程:基础实战篇 待续... 上篇文章介绍了 Linux capabilit ...

  9. docker 概念简介、简单入门

    1.docker 简介 Docker 是一个开源项目,这个项目旨在通过把应用程序打包为可移植的.自给自足的容器(引用语) DocKer一次构建可放在任何地方就可以运行,不需要进行任何改变DocKer  ...

  10. Spring Cloud gateway 三 自定义过滤器GatewayFilter

    之前zuul 网关介绍.他有过滤器周期是四种,也是四种类型的过滤器.而gateway 只有俩种过滤器:"pre" 和 "post". PRE: 这种过滤器在请求 ...