小工具      在线工具  汉语词典  css  js  c++  java

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

# ... .. . MyBatis . .. ...,mybatis,源码分析,if test 失效,值为0时 额外说明

收录于:192天前

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

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 此时,筛选条件不起作用就不足为奇了。
为什么会出现这种情况?是框架问题吗? 感觉不是的,我们在编程的时候,对数值类型值的判断本身就不应该使用 =='' 或者 !=''这样的条件。

. . .

相关推荐

额外说明

Mysql局域网启用外部访问权限

-- mysql 开启远程访问 use mysql; select * from user \G; update user set Host = '%' where Host = 'localhost' and User='root'; flush

额外说明

REDIS21_Cache双写一致性方案,先更新数据库再删除缓存

文章目录 ①. 什么是缓存双写一致 ②. 先更新数据库,再更新缓存 ③. 先删除缓存,再更新数据库 ④. 先更新数据库,再删除缓存 ①. 什么是缓存双写一致 ①. 缓存双写一致性,谈谈你的理解 如果redis中有数据,需要和数据库中的值相同 如果redi

额外说明

uniapp——index页商品列表 与 数据渲染

QQ 1274510382 Wechat JNZ_aming 商业联盟 QQ群538250800 技术搞事 QQ群599020441 解决方案 QQ群152889761 加入我们 QQ群649347320 共享学习 QQ群674240731 纪年科技am

额外说明

TensorFlow2 100 行代码实现 VGG13

TensorFlow2 VGG13 实战 CIFAR100 概述 卷积 代码实现 超参数 网络模型 获取数据 完整代码 概述 VGG13 由是 Oxford 的 Visual Geometry Group 组织提出的经典卷积神经网络. VGG13 由 1

额外说明

ch7_1指令系统

计算机硬件与软件之间的接口, 指令系统。 1.机器指令 1.1 指令的格式 指令的格式是什么? 操作码,地址码,寻址方式; 指令的字长,可以分为固定字长,可变字长; 操作码的长度可以是固定的,也可以是变化的。 操作码 反映机器做什么操作 长度固定: 用于

额外说明

ROS从入门到精通2-1:机器人3D可视化工具——Rviz

目录 0 专栏介绍 1 什么是Rviz? 2 Rviz安装与基本界面 3 Rviz基本数据类型 4 数据可视化 4.1 实例1:显示USB摄像头数据 4.2 实例2:显示球体 0 专栏介绍 本专栏旨在通过对ROS的系统学习,掌握ROS底层基本分布式原理,

额外说明

Response.IsClientConnected 原理和用法

这篇是传自蝈蝈俊的文章,以前曾经想过这个问题,但从未动手实验过,这篇文章很精彩 原文链接:http://blog.csdn.net/ghj1976/archive/2008/07/23/2697276.aspx 问题:当一个正在执行中的ASPX页面执行到

额外说明

解决OnDemandBrokerClient.dll文件丢失缺少在系统内

其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个OnDemandBroker

额外说明

抖音快手影视解说教程

新标题:影视评论教程:打造引人入胜的抖音和快手内容 文章: 在当今的数字时代,抖音、快手等短视频平台已经成为很多人观看和分享影视内容的主要方式。影视解说是一种流行的创作形式。通过对电影、电视剧等影视作品的讲解和评论,吸引了大量观众的关注和订阅。如果你也想

额外说明

Spring Data Elasticsearch 集成测试

1.下载并启动elasticsearch 6.2.2(可以参考我之前的文章) elasticsearch 6.2.2下载地址 2.启动ElasticSearch Head插件(请参考我之前的文章) 3.通过ElasticSearch Head查看ES中的

ads via 小工具