Mybatis踩坑--test语句

mybatis 中 if-test 判断详解 <if test="takeWay == '0'">】mybatis的if判断 单个的字符要写到双引号里面才行,改为<if test='takeWay == "1"'>或者改为<if test="takeWay == '1'.toString() "> .xml文件的部分代码 <insert id="insertDelivery" parameterType="com.zuci.request.DeliveryPreferenceReq"> ... 阅读详情

Mybatis version:3.2.2

问题:如下sql语句,关注点在optStatus != '' 这句上。

select * from table
where ...
    <if test="optStatus != null and optStatus != ''">
           AND OPT_STATUS = #{optStatus,jdbcType=DECIMAL}
    </if>

其中optStatus是数值类型。

此时如果optStatus传入参数为0时,按常理理解这个条件会执行 and OPT_STATUS=0 这个条件,但是诡异的事情发生了,这个条件没有执行,而如果optStatus为非0数字时,能够正常运行。先不说这个奇葩的写法,数值型用!=''判断(这里的用法肯定是不合理的),为啥传入0,看似满足的条件却不满足了呢。二话不说,只能撸源码。

前面就不看了(有兴趣debug一下),直接看重点,因为我们的条件是!=,所以定位到类ASTNotEq,看getValueBody方法:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.apache.ibatis.ognl;

class ASTNotEq extends ExpressionNode {
    public ASTNotEq(int id) {
        super(id);
    }

    public ASTNotEq(OgnlParser p, int id) {
        super(p, id);
    }

    protected Object getValueBody(OgnlContext context, Object source) throws OgnlException {
        Object v1 = super.children[0].getValue(context, source);
        Object v2 = super.children[1].getValue(context, source);
        return OgnlOps.equal(v1, v2) ? Boolean.FALSE : Boolean.TRUE;
    }

    public String getExpressionOperator(int index) {
        return "!=";
    }
}

根据源码,getValueBody方法中的局部变量v1=0,v2='',按常理0!='',OgnlOps.equals(v1,v2)应该返回false才对,这样getValueBody返回TRUE,AND语句才会执行。而真实情况是OgnlOps.equals(v1,v2)返回了True,原因接着看OgnlOps.equal。

public abstract class OgnlOps implements NumericTypes {
   ......
    public static boolean equal(Object v1, Object v2) {
        if (v1 == null) {
            return v2 == null;
        } else if (v1 != v2 && !isEqual(v1, v2)) {
            if (v1 instanceof Number && v2 instanceof Number) {
                return ((Number)v1).doubleValue() == ((Number)v2).doubleValue();
            } else {
                return false;
            }
        } else {
            return true;
        }
    }
   .......
public static boolean isEqual(Object object1, Object object2) {
        boolean result = false;
        if (object1 == object2) {
            result = true;
        } else if (object1 != null && object2 != null) {
            if (object1.getClass().isArray() && object2.getClass().isArray() && object2.getClass() == object1.getClass()) {
                result = Array.getLength(object1) == Array.getLength(object2);
                if (result) {
                    int i = 0;

                    for(int icount = Array.getLength(object1); result && i < icount; ++i) {
                        result = isEqual(Array.get(object1, i), Array.get(object2, i));
                    }
                }
            } else if (object1 != null && object2 != null) {
                result = compareWithConversion(object1, object2, true) == 0 || object1.equals(object2);
            }
        }

        return result;
    }
...............
public static int compareWithConversion(Object v1, Object v2, boolean equals) {
        int result;
        if (v1 == v2) {
            result = 0;
        } else {
            int t1 = getNumericType(v1);
            int t2 = getNumericType(v2);
            int type = getNumericType(t1, t2, true);
            switch(type) {
            case 6:
                result = bigIntValue(v1).compareTo(bigIntValue(v2));
                break;
            case 9:
                result = bigDecValue(v1).compareTo(bigDecValue(v2));
                break;
            case 10:
                if (t1 == 10 && t2 == 10) {
                    if (v1 != null && v2 != null) {
                        if (v1.getClass().isAssignableFrom(v2.getClass()) || v2.getClass().isAssignableFrom(v1.getClass())) {
                            if (v1 instanceof Comparable) {
                                result = ((Comparable)v1).compareTo(v2);
                                break;
                            }

                            if (equals) {
                                result = v1.equals(v2) ? 0 : 1;
                                break;
                            }
                        }

                        if (!equals) {
                            throw new IllegalArgumentException("invalid comparison: " + v1.getClass().getName() + " and " + v2.getClass().getName());
                        }

                        result = 1;
                        break;
                    } else {
                        boolean var10000 = v1 != v2;
                    }
                }
            case 7:
            case 8:
                double dv1 = doubleValue(v1);
                double dv2 = doubleValue(v2);
                return dv1 == dv2 ? 0 : (dv1 < dv2 ? -1 : 1);
            default:
                long lv1 = longValue(v1);
                long lv2 = longValue(v2);
                return lv1 == lv2 ? 0 : (lv1 < lv2 ? -1 : 1);
            }
        }

        return result;
    }
}

 方法执行的顺序是 equals()->isEquals()->compareWithConversion()。根据getNumericType()方法,0返回4,''返回10,type=10,就会走到case 10:语句,而t2=10,t1=4,所以不会进入到if (t1 == 10 && t2 == 10) 语句内,且没有break语句,进而进入case 8:,而doubleValue()对参数0和''均返回0.0D,所以判断为0=='',这就是根源所在。

总结,虽然还没完全理解OGNL里面的这些逻辑,不知道没有break是故意为之还是bug,但是可以确定的是,在使用的时候是不恰当的,数值型的不能和字符串比较。在不改变mybatis和ognl源码的前提下,使用mybatis要注意,test语句的比较表达式要满足类型匹配,否则会有意想不到的惊喜(当然,本文举例在实际应用中自测的情况下很容易发现问题)。

永磁同步电机矢量控制——从三相静止坐标系到d-q坐标系的数学转换 本文深入解析了永磁同步电机矢量控制的核心——从三相静止坐标系到d-q旋转坐标系的数学转换。通过Clark变换和Park变换,将复杂的三相交流系统解耦为易于控制的直流量,从而实现对电机转矩和磁场的独立、精准控制。文章结合物理图像与工程实践,详细阐述了坐标变换的原理、公式推导及其在磁场定向控制(FOC)中的关键作用。 阅读详情

相关推荐

STM32duino LSM6DSO驱动库:低功耗IMU工程化实践

惯性测量单元(IMU)是智能终端与工业设备实现运动感知的核心传感器,其性能关键在于数据精度、实时响应与系统功耗的协同优化。LSM6DSO作为集成加速度计与陀螺仪的六轴MEMS器件,依托片上有限状态机(FSM)和机器学习核心(MLC),支持自由落体检测、计步器、6D方向识别等硬件自治功能,显著降低主控CPU负载。在STM32平台下,通过深度耦合HAL/LL库、显式引脚管理、DMA加速SPI传输及EXTI中断协同,可实现亚毫秒级事件响应与微安级待机功耗。本文聚焦STM32duino生态中LSM6DSO驱动的工程

weixin_36304957的博客 551

mybatis中的test语句

mybatis中mapper.xml中的test语法 &lt;if test="param.status != null and param.status != ''"&gt; &lt;if test="param.status == '完成'"&gt; AND b.status = '完成' &lt;/if&gt; &lt;/if...

qq_37291187的博客 1万+

异步bus交互(一)— 两级DFF同步器

异步bus交互(一)— 两级DFF同步器 跨时钟域处理 & 亚稳态处理 1.问题产生 现在的芯片(比如SOC,片上系统)集成度和复杂度越来越高,通常一颗芯片上会有许多不同的信号工作在不同的时钟频率下。比如SOC芯片中的CPU通常会工作在一个频率上,总线信号(比如DRAM BUS)会工作在另一个时钟频率下,而普通的信号又会工作在另外的时钟频率下。这3个不同时钟频率下工作的信号往往需要相互沟通和传递信号。 不同时钟域下的信号传递就涉及到跨时钟域信号处理,因为相互之间的频率、相位不一样,如果不做处理或者

qq_44816673的博客 5120

myBatis 查询时注意and拼接条件

&lt;!-- 加个条件 --&gt;      &lt;sql id="queryjiachaAllPageId"&gt;         &lt;where&gt;             &lt;if test="danweimc !=null and danweimc !=''"&gt;                 and jcb.danweimc like '%${danweim...

探索丶挑战丶突破 7535

DEA各种模型原理及stata代码实现

DEA各种模型原理及stata代码实现DEA各种模型原理及stata代码实现一、CCR和BCC1.原理2.效率测算stata代码3.Malmquist指数3.1M指数3.2Global-Malmquist指数4.指数计算代码与案例二、SBM模型1.原理2.stata代码实现三、方向性距离函数(DDF)1.原理2.stata代码实现3.非径向DDF模型(NDDF)3.GML指数4.指数测算四、总结 DEA各种模型原理及stata代码实现 一、CCR和BCC 1.原理 CCR模型产出导向下的效率通过求解以下规划

wonder1322的博客 4万+

生物信息学实战:如何用STRING数据库和R语言搞定蛋白互作网络分析(附完整代码)

本文提供了一份完整的生物信息学实战指南,详细介绍了如何利用STRING数据库和R语言进行蛋白互作网络分析。从差异表达基因列表出发,涵盖数据准备、数据库连接、网络构建到高级可视化与模块识别的全流程,并附有可复现的完整R代码,帮助研究人员深入解析转录组数据背后的蛋白互作关系。

milk5的博客 946

mybatis sql查询动态标签消除 and 和 or 的方法

mybatis sql查询动态标签消除 and 和 or的方法。第一种:学会用 等标签第二种:同时需要掌握 1=1 和 1=0 在mybatis sql中的妙用

qq_34168515的博客 3505

python画弗里德曼(Friedman) 检验和秩和检验(Nemenyi)检验图

python画弗里德曼(Friedman) 检验和秩和检验(Nemenyi)检验图 画好后效果图 实现代码如下 import matplotlib.pyplot as plt #算法平均排名 _alg_=[1.405,2.643,2.786,2.167] y=[1,2,3,4]#alg1,alg2,alg3,alg4 通过Nemenyi测试计算得到的临界值CD CD=1.024 h_CD=CD/2 plt.figure(figsize=(10,6)) plt.scatter(_alg_,y,s=10

大模型天花板 4464

05 MyBatis 动态SQL&&标签

一个查询的方法的Sql语句不一定是固定的。比如电商网站的查询商品,用户使用不同条件查询,Sql语句就会添加不同的查询条件。此时就需要在方法中使用动态Sql语句。 标签:、、、

m0_51697147的博客 2798

【Unity Shader】2D模型 3D模型混用的穿模问题(Spine在3D场景中出现前后穿模问题的解决办法)

问题描述: 在3D场景中使用Spine模型(2D), 因为Spine需要像Billboard类似的处理,永远是垂直与相机的, 所以一般情况下2D模型能正常显示且前后的阻挡关系也是没有问题的,如下图所示,一切都很美好.(这里用一个四边形,图中的福字表示2D模型) 可是如果后面蓝色的格子比较高,或者2D角色本身也比较高,那么就会出现模型穿插的问题,如下图所示: 如果吧2D模型竖立起来,前后关系肯定是没有问题的,所以也能避免模型穿插的问题,可是就没有Billboard效果,圆形的福字已经被压扁了,如下图:

Vitens的专栏 4590

CMake是什么?为什么学习CMake

CMake的主要作用和重要性,包括其在跨平台构建中的应用、如何支持多种编译器及操作系统,以及它在管理大型和复杂项目中的优势。

小鱼酱的博客 3870

mybatis的test坑(不等于‘‘ 且 不等于0)

mybatis使用xml过程中我们经常会遇到要进行动态sql的判断,如使用if标签和choose标签中的when标签,都会遇到test条件判断,test的条件判断采用的ognl语句。

Lou_Lan的博客 3694

从零开始学 AUTOSAR:深入浅出 SAE J1939 诊断通信管理器(J1939Dcm)深度完整版

SAE J1939 是美国汽车工程师学会制定的重型车辆 CAN 总线通信标准,覆盖卡车、客车、工程机械、农机、船舶等,是商用车领域的 “通用语言”。基于CAN 2.0B 扩展帧(29 位 ID)(车规主流)PGN(参数组号)+ SPN(可疑参数号)核心标准:J1939-21:数据链路层(CAN 帧格式、地址声明)J1939-71:应用层(普通信号、报文)诊断层(核心!J1939Dcm 依据)J1939-81:网络管理(地址管理、节点检测)

getusushu的博客 116

mybatis的mapper.xml文件中update语句条件判断踩坑记录“<if test>”标签

这里执行完之后会把“condition”里面的“status”字段更新为“2”,无论接口入参里面传什么值,这里“status”都会被更新为“2”;今天遇到个让人摸不着头脑的问题,update语句条件里面的“status”字段赋值为“1”,代码执行完数据库更新为“2”;检查代码逻辑、检查sql语法都没查到问题,不得已逐行打日志,最终定位到是sql执行过程中出的问题;基本语法可能都知道,就是在写代码的时候容易忽略这些细节,记录一下共勉。

Clarence_Pang的博客 2173

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Mybatis的批量更新踩坑

在使用mybatis的批量更新的时候 <update id="updateBatch" parameterType="java.util.List"> <foreach collection="list" item="item" index="index" open="" close="" separator=";"> update stude...

Mr Zhang的博客 802

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

mybatis if test踩坑记录

背景 使用mybatis进行sql查询时,当存在可选参数时,难免会使用的if标签进行判断参数是否存在,如果存在则当做参数拼接到sql中进行查询,否则丢弃 复制代码 现象 当截图中代码是Integer,Long类型时,传入age=0,框中代码输出结果为false;age=1时,为true; 解决方案 当入参为Long,Integer等非字符串类型时,if test不能使用param!='' (理解...

weixin_33719619的博客 662

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

mybatis的 choose -- when test -- otherwise 标签和 if test 标签

1.choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。 当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql。类似于Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。例如下面例子,同样把所有可以限制的条件都写上,...

li_jiazhi的博客 7287

mybatis test使用时遇到的坑

前言 好记性不如烂笔头,工作中有些不是很常用的东西,没过多久就又忘了,写博客是便于自己后面使用时更快的提升工作效率,避免重复踩坑。这里引用网上其他作者的分享进行一个总结记录。 test中字符串的比较 customerType 是String 类型的 test="customerType == ‘0’ " 这样判断的话 会发现执行到 引用...

hbn1326317071的博客 1169

mybatis踩坑值 <if test=> 不能用大写AND

test中AND改成小写就OK了。

qq_35129986的博客 539

springboot mybatis和test

1、依赖 <!--web核心依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--mysql数据库驱

BusyMonkey 574

记录一次mybatis的test语句bug

项目场景: mybatis3.3 mapper的test语句 问题描述: Dao.java Map<String,Object> parm = new HashMap<>(); map.put("key","A"); mapper.xml ... <if test="parm.key='A'"> Exception in thread "main" org.apache.ibatis.exception.PersistenceException: ###

dang 251

【踩坑记录】Mybatis动态SQL表达式test

问题描述:当我遇到了字符串等值判断的时候,坑来了 错误代码镇楼: &lt;choose&gt; &lt;when test="pictureDTO.isFree = '是' "&gt; 1, &lt;/when&gt; ...

一气道盟王富贵儿 2298

mybatis 动态语句

目录 基础 if 语句 if语句判断 数字类型 字符串 if+where语句 if+set 语句 choose(when,otherwise) 语句 trim 语句 SQL 片段 foreach 语句 基础 MyBatis的动态SQL语句是基于OGNL表达式的。可以方便的在SQL语句中实现某些逻辑,总体说来MyBatis动态SQL语句主要有以下几类: 1、if语句(简...

今天吃了吗的博客 2227

mybatis日期比较踩过的坑

下面是我使用mybatis比较日期踩过的坑,分享大家。 首先直接上有问题的代码 <if test=" date != null and date != '' "> and hiredate &lt;=#{date} </if> 报错提示如下: org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: java.lang.IllegalArgumen

qq_44027353的博客 1290

MyBatis if test 判断字符串踩坑

MyBatis if test 判断字符串是否相等

搬运Gong 7217

mybatis if test对Intger判空的坑、原理及解决方法

源码分析MyBatis对Integer类型进行test判断的坑,及解决方法

weixin_49114503的博客 2902
上一篇: Java web获取客户端IP
下一篇: java.lang.NoSuchMethodError出现的一种诡异情况
和泥小工
博客等级 码龄16年 1粉丝 7原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值