这个问题有不少小伙伴遇到过,也给出了解决方案,但是没有探究原因,这次读一下源码,看看原因在哪里。

1. 条件失效情况复现

  • Mapper.xml内的动态SQL如下【伪代码】
 <select id="getInfoList" parameterType="java.util.Map" resultType="java.util.Map">SELECT*${schemaName}${tableName}<where><if test="viewId != null and viewId != ''">AND viewid = #{viewId}</if></where></select>
  • 调用动态SQL的方法如下【伪代码主要是显示一下传递的参数值】
Map<String, Object> mapParam = new HashMap<>(4);
mapParam.put("schemaName", "public");
mapParam.put("tableName", "info_table");
mapParam.put("viewId", 0);
queryInterface.getInfoList(mapParam);

查看查询结果会发现对 viewId 没有进行筛选。

2. 解决方法

去掉判断条件 and viewId != '' 即可。

 <select id="getInfoList" parameterType="java.util.Map" resultType="java.util.Map">SELECT*${schemaName}${tableName}<where><if test="viewId != null">AND viewid = #{viewId}</if></where></select>

3. 源码解析

到底是为什么呢?我们找到 Mybatis 的 IfSqlNode 对象:


下边是打断点进行的参数追踪:

evaluator.evaluateBoolean(test, context.getBindings()) 为 true 时当前节点才会被应用。

进入 evaluateBoolean(test, context.getBindings()) 方法。

进入 OgnlCache.getValue(expression, parameterObject) 方法。
关键方法出现了:Ognl.getValue(parseExpression(expression), context, root);

我们找到 Ognl.getValue(parseExpression(expression), context, root)方法。

中间省略了部分方法,省略的方法主要是查找参数名称和参数值,不重要故未贴出。还有判断节点类型的过程,例子中用的的都是不等于类型的节点。下边的方法真正开始对表达式两侧的数值进行比较了。前半段的 viewId != null 不再贴出,只截图有问题的后半段:


进入最核心的方法比较方法 compareWithConversion(Object v1, Object v2)

看一下转换的过程:

问题的核心代码:

public static double doubleValue(Object value) throws NumberFormatException {if (value == null) {return 0.0D;} else {Class c = value.getClass();if (c.getSuperclass() == Number.class) {return ((Number)value).doubleValue();} else if (c == Boolean.class) {return (Boolean)value ? 1.0D : 0.0D;} else if (c == Character.class) {return (double)(Character)value;} else {String s = stringValue(value, true);return s.length() == 0 ? 0.0D : Double.parseDouble(s);}}}

由于 "".length() = 0,传递的参数 viewId 值是 0️⃣ 时 viewId != '' 就变成 0.0 != 0.0 这个自然是 false 此时,筛选条件不起作用就不足为奇了。
为什么会出现这种情况?是框架问题吗? 感觉不是的,我们在编程的时候,对数值类型值的判断本身就不应该使用 =='' 或者 !=''这样的条件。

【MyBatis使用】mapper.xml 文件内<if test>标签判断参数值不等于null和空 当参数值为 0 时筛选条件失效原因分析(源码探究)相关推荐

  1. 【项目经验】如果想在mapper.xml文件中的一个标签中写多条sql语句,则需要在jdbc的配置文件中稍做配置

    如果想在mapper.xml文件中的一个标签中写多条sql语句,则需要在jdbc的配置文件中稍做配置: url=jdbc:mysql://127.0.0.1:3306/airipo?useUnicod ...

  2. mybatis的mapper.xml文件中含有中文注释时运行出错,mybatis配置优化和别名优化 mybatis配置之映射器说明

    记录一个发现的小问题,刚刚在UserMapper.xml文件中有一段中文注释掉的内容: <!-- <resultMap id="Usermap" type=" ...

  3. Mybatis的mapper.xml文件对大于号和小于号进行处理

    项目中的数据库用到的日期类型是TIMESTAMP,然后就查了一下,TIMESTAMP和Date的区别, date类型存储数据的格式为年月日时分秒,可以精确到秒 timestamp类型存储数据的格式为年 ...

  4. java mapper xml if_bug篇——Mybatis中Mapper.xml文件的if判断问题

    一.问题描述 上述表达,当传入参数validCoupon的值为"1"时,仍然不能执行if判断下的sql语句. 二.剖析原因 public class ExpressionEvalu ...

  5. 【Mybatis】 mapper XML 文件中使用 association 实现一对一关联

    前言 Mybatis 一对一,使用 association 标签 Mybatis 一对多,使用 collection 标签 本文主要说明 association 标签. collection 标签与之 ...

  6. 【Mybatis】 mapper XML 文件中使用 collection实现一对多关联

    前言 Mybatis 一对一,使用 association 标签 Mybatis 一对多,使用 collection 标签 本文主要说明 collection 实现一对多关联.使用 associati ...

  7. Mybatis中Mapper.xml文件sql中动态获取----#{}和${}区别

    1. #{} 获取参数的内容,支持索引获取,param1获取指定位置参数,并且sql使用?占位符 2. ${} 纯字符串拼接,不使用?,默认找${内容}内容的get/set方法,如果写数字,就是一个数 ...

  8. mybatis 鉴别其_MyBatis之Mapper XML 文件详解(四)-JDBC 类型和嵌套查询

    MyBatis之Mapper XML 文件详解(四)-JDBC 类型和嵌套查询 白玉 IT哈哈 支持的 JDBC 类型 为了未来的参考,MyBatis 通过包含的 jdbcType 枚举型,支持下面的 ...

  9. Mybatis实现*mapper.xml热部署-分子级更新

    需求: 项目在开发阶段或是修复bug阶段,会有修改mybatis的mapper.xml的时候,修改一般情况都要重启才能生失效,如果是分布式项目重启有时会耗时很久,都是无尽的等待.如果频繁修改,那么时间 ...

最新文章

  1. linux carry php Soap 扩展
  2. 曲苑杂坛--收缩数据库文件
  3. 安卓版文字扫描识别软件
  4. 密度聚类、密度聚类过程、OPTICS算法
  5. python中处理日期和时间的标准模块是-datetime
  6. 业务逻辑实现方式选择
  7. P4015 运输问题
  8. bootstrap 生日选择_bootstrap的datetimepicker只选择月份
  9. c语言程序设计及gis,C语言程序设计(西安工程大学)2020知到答案全套
  10. 游戏开发之C++多继承及虚继承(C++基础)
  11. 锤子发布会2018的四个环节概述
  12. 【Scratch】青少年蓝桥杯_每日一题_10.09_小猫奔跑
  13. [Introduction to programming in Java 笔记] 1.3.8 Gambler's ruin simulation 赌徒破产模拟
  14. 人都有说话的功能,中国人说汉语,美国人说英语,试用多态思想描述这一情形
  15. SAP中Quant份的理论及应用解析
  16. Python将两个列表合并为一个字典
  17. Mac下Aria2安装与使用
  18. C++语言程序设计【1】
  19. WPF简易局部地图 实现标记 绘制轨迹
  20. Schwinger-boson自旋表示

热门文章

  1. skyline TerraBuilder 制作MPT方法与技巧(2)(转自)
  2. Json.NET Deserialize时如何忽略$id等特殊属性
  3. 基于visual Studio2013解决C语言竞赛题之1070删除相同节点
  4. linux多进程编程计算圆周率,中值积分定理计算PI值的多线程实现
  5. laravel框架中文手册_laravel请求参数校验方法
  6. 配置一个Servlet可以被一个(指定的开头链接,后自定义)访问
  7. linux的fork语句,Linux C/C++——fork()函数基础
  8. java中方法的具体化_我为什么要关心Java没有具体化的泛型?
  9. mybatis mysql crud_Mybatis实现CRUD操作
  10. php 通过相对或得绝对,相对路径与绝对路径的了解与深入