【MyBatis使用】mapper.xml 文件内<if test>标签判断参数值不等于null和空 当参数值为 0 时筛选条件失效原因分析(源码探究)
这个问题有不少小伙伴遇到过,也给出了解决方案,但是没有探究原因,这次读一下源码,看看原因在哪里。
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 时筛选条件失效原因分析(源码探究)相关推荐
- 【项目经验】如果想在mapper.xml文件中的一个标签中写多条sql语句,则需要在jdbc的配置文件中稍做配置
如果想在mapper.xml文件中的一个标签中写多条sql语句,则需要在jdbc的配置文件中稍做配置: url=jdbc:mysql://127.0.0.1:3306/airipo?useUnicod ...
- mybatis的mapper.xml文件中含有中文注释时运行出错,mybatis配置优化和别名优化 mybatis配置之映射器说明
记录一个发现的小问题,刚刚在UserMapper.xml文件中有一段中文注释掉的内容: <!-- <resultMap id="Usermap" type=" ...
- Mybatis的mapper.xml文件对大于号和小于号进行处理
项目中的数据库用到的日期类型是TIMESTAMP,然后就查了一下,TIMESTAMP和Date的区别, date类型存储数据的格式为年月日时分秒,可以精确到秒 timestamp类型存储数据的格式为年 ...
- java mapper xml if_bug篇——Mybatis中Mapper.xml文件的if判断问题
一.问题描述 上述表达,当传入参数validCoupon的值为"1"时,仍然不能执行if判断下的sql语句. 二.剖析原因 public class ExpressionEvalu ...
- 【Mybatis】 mapper XML 文件中使用 association 实现一对一关联
前言 Mybatis 一对一,使用 association 标签 Mybatis 一对多,使用 collection 标签 本文主要说明 association 标签. collection 标签与之 ...
- 【Mybatis】 mapper XML 文件中使用 collection实现一对多关联
前言 Mybatis 一对一,使用 association 标签 Mybatis 一对多,使用 collection 标签 本文主要说明 collection 实现一对多关联.使用 associati ...
- Mybatis中Mapper.xml文件sql中动态获取----#{}和${}区别
1. #{} 获取参数的内容,支持索引获取,param1获取指定位置参数,并且sql使用?占位符 2. ${} 纯字符串拼接,不使用?,默认找${内容}内容的get/set方法,如果写数字,就是一个数 ...
- mybatis 鉴别其_MyBatis之Mapper XML 文件详解(四)-JDBC 类型和嵌套查询
MyBatis之Mapper XML 文件详解(四)-JDBC 类型和嵌套查询 白玉 IT哈哈 支持的 JDBC 类型 为了未来的参考,MyBatis 通过包含的 jdbcType 枚举型,支持下面的 ...
- Mybatis实现*mapper.xml热部署-分子级更新
需求: 项目在开发阶段或是修复bug阶段,会有修改mybatis的mapper.xml的时候,修改一般情况都要重启才能生失效,如果是分布式项目重启有时会耗时很久,都是无尽的等待.如果频繁修改,那么时间 ...
最新文章
- linux carry php Soap 扩展
- 曲苑杂坛--收缩数据库文件
- 安卓版文字扫描识别软件
- 密度聚类、密度聚类过程、OPTICS算法
- python中处理日期和时间的标准模块是-datetime
- 业务逻辑实现方式选择
- P4015 运输问题
- bootstrap 生日选择_bootstrap的datetimepicker只选择月份
- c语言程序设计及gis,C语言程序设计(西安工程大学)2020知到答案全套
- 游戏开发之C++多继承及虚继承(C++基础)
- 锤子发布会2018的四个环节概述
- 【Scratch】青少年蓝桥杯_每日一题_10.09_小猫奔跑
- [Introduction to programming in Java 笔记] 1.3.8 Gambler's ruin simulation 赌徒破产模拟
- 人都有说话的功能,中国人说汉语,美国人说英语,试用多态思想描述这一情形
- SAP中Quant份的理论及应用解析
- Python将两个列表合并为一个字典
- Mac下Aria2安装与使用
- C++语言程序设计【1】
- WPF简易局部地图 实现标记 绘制轨迹
- Schwinger-boson自旋表示
热门文章
- skyline TerraBuilder 制作MPT方法与技巧(2)(转自)
- Json.NET Deserialize时如何忽略$id等特殊属性
- 基于visual Studio2013解决C语言竞赛题之1070删除相同节点
- linux多进程编程计算圆周率,中值积分定理计算PI值的多线程实现
- laravel框架中文手册_laravel请求参数校验方法
- 配置一个Servlet可以被一个(指定的开头链接,后自定义)访问
- linux的fork语句,Linux C/C++——fork()函数基础
- java中方法的具体化_我为什么要关心Java没有具体化的泛型?
- mybatis mysql crud_Mybatis实现CRUD操作
- php 通过相对或得绝对,相对路径与绝对路径的了解与深入