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

简介: MyBatis【源码探究 01】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 此时,筛选条件不起作用就不足为奇了。

为什么会出现这种情况?是框架问题吗? 感觉不是的,我们在编程的时候,对数值类型值的判断本身就不应该使用 =='' 或者 !=''这样的条件。

目录
相关文章
|
SQL XML Java
mybatis-源码深入分析(一)
mybatis-源码深入分析(一)
|
SQL XML Java
菜鸟之路Day35一一Mybatis之XML映射与动态SQL
本文介绍了MyBatis框架中XML映射与动态SQL的使用方法,作者通过实例详细解析了XML映射文件的配置规范,包括namespace、id和resultType的设置。文章还对比了注解与XML映射的优缺点,强调复杂SQL更适合XML方式。在动态SQL部分,重点讲解了`&lt;if&gt;`、`&lt;where&gt;`、`&lt;set&gt;`、`&lt;foreach&gt;`等标签的应用场景,如条件查询、动态更新和批量删除,并通过代码示例展示了其灵活性与实用性。最后,通过`&lt;sql&gt;`和`&lt;include&gt;`实现代码复用,优化维护效率。
1478 5
|
XML Java 数据库连接
二、搭建MyBatis采用xml方式,验证CRUD(增删改查操作)
二、搭建MyBatis采用xml方式,验证CRUD(增删改查操作)
556 21
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
SQL Java 数据库连接
【潜意识Java】深入理解MyBatis的Mapper层,以及让数据访问更高效的详细分析
深入理解MyBatis的Mapper层,以及让数据访问更高效的详细分析
3304 1
|
SQL Java 数据库连接
Mybatis入门(select标签)
这篇文章介绍了Mybatis中`select`标签的基本用法及其相关属性,并通过示例展示了如何配置和执行SQL查询语句。
524 1
Mybatis入门(select标签)
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
文章介绍了MyBatis中动态SQL的用法,包括if、choose、where、set和trim标签,以及foreach标签的详细使用。通过实际代码示例,展示了如何根据条件动态构建查询、更新和批量插入操作的SQL语句。
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
文章介绍了MyBatis中高级查询的一对多和多对一映射处理,包括创建数据库表、抽象对应的实体类、使用resultMap中的association和collection标签进行映射处理,以及如何实现级联查询和分步查询。此外,还补充了延迟加载的设置和用法。
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
|
SQL XML Java
Mybatis的<where>,<if>等标签用法
这篇文章详细解释了Mybatis中<where>和<if>等标签的用法,展示了如何在SQL动态构建中有效地过滤条件和处理逻辑分支。
1327 1
|
SQL XML Java
mybatis :sqlmapconfig.xml配置 ++++Mapper XML 文件(sql/insert/delete/update/select)(增删改查)用法
当然,这些仅是MyBatis功能的初步介绍。MyBatis还提供了高级特性,如动态SQL、类型处理器、插件等,可以进一步提供对数据库交互的强大支持和灵活性。希望上述内容对您理解MyBatis的基本操作有所帮助。在实际使用中,您可能还需要根据具体的业务要求调整和优化SQL语句和配置。
532 1

热门文章

最新文章