广告
返回顶部
首页 > 资讯 > 后端开发 > Python >mybatisiftest条件判断语句中的判断问题分析
  • 741
分享到

mybatisiftest条件判断语句中的判断问题分析

2024-04-02 19:04:59 741人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录if test条件判断语句中的判断问题我在mybatis中定义的sql语句如下或使用equals()mybatis 中if test判断大坑使用Mybatis时,常常会判断属性是

if test条件判断语句中的判断问题

写这个主要是描述在mybatis中要注意的问题,很不幸,自己没注意,跳坑了。

我在mybatis中定义的sql语句如下

<if test="facilityOccupied != null and facilityOccupied != '' and facilityOccupied == 1 ">
                and z.serviceCount = 1
            </if>    
            <if test="facilityOccupied != null and facilityOccupied != '' and facilityOccupied == 0 ">
                and z.serviceCount = 0
            </if>

可以看到这里只是对传入参数一个简单的判断。

controller层传入一个Integer类型的facilityOccupied参数。

表面上看没什么问题,当传入facilityOccupied = 1,测试结果很意外,它查询了所有的结果,也就是说它没有符合这个判断facilityOccupied == 1 。

换一种写法,在controller层中将传入参数facilityOccupied改为String类型的,通过查询结果可以看出它符合facilityOccupied == 1 这个判断条件。

或使用equals()

<if test="facilityOccupied != null and facilityOccupied != '' and facilityOccupied.equals(1)">
                and z.serviceCount = 1
            </if>    
            <if test="facilityOccupied != null and facilityOccupied != '' and facilityOccupied.equals(0)">
                and z.serviceCount = 0
            </if>

所以,总结起来怎么说,在这个地方比较的并不是数值大小,而是物理地址,这个双引号里面的1不是int类型也不是integer类型,而是String字符串类型,啊多么痛的领悟。

补充一下,test中eq 和 == 效果一样,比较的是地址,所以比较值最好使用equals()。

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">     
    insert cx_customer_deliverypreference     
    <trim prefix="(" suffix=")" suffixOverrides=",">           
        .... 此处省略       
        <if test="takeWay == '1' and workday != null ">         
            WORKDAY,       
        </if>       
        ....     
    </trim>
         
    <trim prefix="values (" suffix=")" suffixOverrides=",">          
        .... 此处省略          
        <if test="takeWay == '1' and workday != null ">            
            #{workday, jdbcType=VARCHAR},     
        </if>      
        ....   
    </trim>
</insert>

takeWay == “1”处出错,导致不执行if判断中的sql,运行程序不报错,没有任何提示。去掉takeWay == “1” and 则可执行。对此我百思不得其解,

因为自己有写过如下代码,是没错的。

<if test="messageType == 'senderReceiveSuccess' ">
      ......
</if>
  • 把<if test="takeWay == '1' and workday != null ">
  • 改为<if test='takeWay == "1" and workday != null '>
  • 或改为<if test="takeWay == '1'.toString() and workday != null ">即可。

原因是:mybatis是用OGNL表达式来解析的,在OGNL的表达式中,’1’会被解析成字符,java是强类型的,char 和 一个string 会导致不等,所以if标签中的sql不会被解析。

总结下使用方法:单个的字符要写到双引号里面或者使用.toString()才行!

使用Mybatis时,常常会判断属性是否为空

POJO

private Integer status;//状态,可能为0、1、2、3。

Mapper XML

<sql>
  <trim prefix="where" prefixOverrides="and | or ">
      //...省略其他
      <if test="status != null and status !=''">and status = #{status}</if> 
  <trim prefix="where" prefixOverrides="and | or ">
</sql>
  • 当status的值为 0时该where SQL and status = 0并未正常拼接,也就是说test内的表达式为false,从而导致查询结果错误。但是,显然该值(Integer :0)!= null也!= ' ',应该为true才对。
  • 当status为Integer类型,并且status值为0时,该if判断却为false。
  • 当status为0时,Mybatis会解析成'' 空字符串。

为了避免这个问题,改成下面这样写,去掉对空字符的判断,就解决了该问题

<if test="status != null">and status = #{status}</if> 

原因分析

通过Debug MyBatis源码顺藤摸瓜找到了IfSqlnode类,该类用来处理动态SQL的<if>节点,方法public boolean apply(DynamicContext context)用来构造节点内的SQL语句。if (evaluator.evaluateBoolean(test, context.getBindings())该代码便是解析<if test="status !=null and status !=''">test内表达式的关键,如果表达式为true则拼接SQL,否则忽略。

public class IfSqlNode implements SqlNode {
  private ExpressionEvaluator evaluator;
  private String test;
  private SqlNode contents;
  public IfSqlNode(SqlNode contents, String test) {
    this.test = test;
    this.contents = contents;
    this.evaluator = new ExpressionEvaluator();
  }
  public boolean apply(DynamicContext context) {
    if (evaluator.evaluateBoolean(test, context.getBindings())) {
      contents.apply(context);
      return true;
    }
    return false;
  }
}

打开ExpressionEvaluator 类,发现解析表达式使用的是OGNL,如果你使用过古老的Struts框架你应该对它不陌生。通过OgnlCache.getValue(expression, parameterObject);可以看到表达式的值是从缓存中获取的,由此可知MyBatis竟然对表达式也做了缓存,以提高性能。

public class ExpressionEvaluator {  
  public boolean evaluateBoolean(String expression, Object parameterObject) {  
    Object value = OgnlCache.getValue(expression, parameterObject);  
    if (value instanceof Boolean) return (Boolean) value;  
    if (value instanceof Number) return !new BigDecimal(String.valueOf(value)).equals(BigDecimal.ZERO);  
    return value != null;  
  }  

跟进去看看,终于找到了解析表达式的方法private static Object parseExpression(String expression),该方法会先从缓存取值,如果没有便进行解析并放入缓存中,然后调用Ognl.getValue(parseExpression(expression), root)获得表达式的值。

public class OgnlCache {
  private static final Map<String, ognl.Node> expressionCache = new ConcurrentHashMap<String, ognl.Node>();
  public static Object getValue(String expression, Object root) throws OgnlException {
    return Ognl.getValue(parseExpression(expression), root);
  }
  private static Object parseExpression(String expression) throws OgnlException {
    try {
      Node node = expressionCache.get(expression);
      if (node == null) {
        node = new OgNLParser(new StringReader(expression)).topLevelExpression();
        expressionCache.put(expression, node);
      }
      return node;
    } catch (ParseException e) {
      throw new ExpressionSyntaxException(expression, e);
    } catch (TokenMgrError e) {
      throw new ExpressionSyntaxException(expression, e);
    }
  }

至于Ognl.getValue(parseExpression(expression), root)是如何运作的,如果你有兴趣可以自行跟下去一探究竟,本文就不赘述了。到此为止,我们已经知道MyBatis的表达式是用OGNL处理的了,这一点已经够了。下面我们去OGNL官网看看是不是我们的表达式语法有问题从而导致该问题的发生。

Interpreting Objects as Booleans

Any object can be used where a boolean is required. OGNL interprets objects as booleans like this:

If the object is a Boolean, its value is extracted and returned;

If the object is a Number, its double-precision floating-point value is compared with zero; non-zero is treated as true, zero as false;

If the object is a Character, its boolean value is true if and only if its char value is non-zero;

Otherwise, its boolean value is true if and only if it is non-null.

果然,如果对象是一个Number类型,值为0时将被解析为false,否则为true,浮点型0.00也是如此。OGNL对于boolean的定义和javascript有点像,即'' == 0 == false。这也就不难理解<if test="status != null and status !=''">and status = #{status}</if>当status=0时出现的问题了,显然0!=''是不成立的,导致表达式的值为false。

将表达式修改为<if test="status != null">and status = #{status}</if>该问题便迎刃而解。该问题的根源还是来自编码的不规范,只有String类型才需要判断是否!='',其他类型完全没有这个必要,可能是开发人员为了省事直接复制上一行拿过来改一改或是所使用的MyBatis生成工具不严谨导致该问题的发生。

这里有必要再提一个“坑”,如果你有类似于String str ="A"; <if test="str!= null and str == 'A'">这样的写法时,你要小心了。因为单引号内如果为单个字符时,OGNL将会识别为Java 中的 char类型,显然String 类型与char类型做==运算会返回false,从而导致表达式不成立。解决方法很简单,修改为<if test='str!= null and str == "A"'>即可。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。 

--结束END--

本文标题: mybatisiftest条件判断语句中的判断问题分析

本文链接: https://www.lsjlt.com/news/142250.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • mybatisiftest条件判断语句中的判断问题分析
    目录if test条件判断语句中的判断问题我在mybatis中定义的sql语句如下或使用equals()mybatis 中if test判断大坑使用Mybatis时,常常会判断属性是...
    99+
    2022-11-13
  • mybatis if test条件判断语句中的判断问题实例分析
    本文小编为大家详细介绍“mybatis if test条件判断语句中的判断问题实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“mybatis if test条件判断语句中的判断问题实例分析”文...
    99+
    2023-06-29
  • python中的条件判断语句
    在python中使用条件判断语句一定不要忘记if else elif后面的冒号:哦 if语句的特点: 从上往下判断,如果某一个判断是true,将该判断条件对应的语句执行,忽略后面剩下的else和elif 1、用if语句实现 如果判断结果...
    99+
    2023-01-31
    语句 条件 python
  • Python的条件判断语句------i
      计算机之所以能做很多自动化的任务,因为它可以自己做条件判断。   比如,输入用户的年龄,根据年龄打印不同的内容。。。   Python程序中,能让计算机自己作出判断的语句就是if语句:   例:     age = 25     if...
    99+
    2023-01-31
    语句 条件 Python
  •  python中的条件判断语句怎么用
    这篇文章主要为大家展示了“ python中的条件判断语句怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“ python中的条件判断语句怎么用”这篇文章吧。1. 避免多层分...
    99+
    2023-06-29
  • python中的条件判断语句的使用介绍
    目录1. 避免多层分支嵌套2. 封装过于复杂的逻辑判断3. 不同分支下的重复代码4. 合理使用三元表达式5. 常见技巧5.1德摩根定律5.2自定义类的魔法方法5.3在条件判断中使用 ...
    99+
    2022-11-13
  • linux中如何使用shell 条件判断语句
    linux中如何使用shell 条件判断语句,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。常用系统变量 $0 当前程式的名称 $n 当前程式的第n个参数,n=1,2,&am...
    99+
    2023-06-13
  • JS if else语句(条件判断语句)的详细使用
    目录前言if语句if else 语句if else if else 语句总结前言 条件判断语句是程序开发过程中一种经常使用的语句形式,和大部分编程语言相同,JavaScript&nb...
    99+
    2022-11-13
  • dos if条件判断语句的实例用法
    这篇文章主要讲解了“dos if条件判断语句的实例用法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“dos if条件判断语句的实例用法”吧!判断驱动器、文件或文件夹是否存在,用 if exi...
    99+
    2023-06-09
  • Python中的条件判断语句与循环语句用法小结
    if语句 >>通用格式 if语句一般形式如下: if <test1>: <statements1> elif <test2>: <stateme...
    99+
    2022-06-04
    语句 小结 条件
  • Python中的if判断语句中包含or问题
    目录Python if判断语句中包含orpython中if相关语句1.if语句2.if-else语句 3.if-elif-else(多重判断)语句4.if嵌套语句5.猜拳小...
    99+
    2022-11-11
  • Python中的条件判断语句基础学习教程
    if语句用来检验一个条件, 如果 条件为真,我们运行一块语句(称为 if-块 ), 否则 我们处理另外一块语句(称为 else-块 )。 else 从句是可选的。 使用if语句: #!/usr/bin...
    99+
    2022-06-04
    语句 条件 基础
  • linux脚本判断条件的示例分析
    小编给大家分享一下linux脚本判断条件的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!如下所示:-b file 若文件存在且是一个块特殊文件,则为真-c...
    99+
    2023-06-09
  • SQL Server中使用判断语句的实例分析
    本篇内容主要讲解“SQL Server中使用判断语句的实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SQL Server中使用判断语句的实例分析”吧!SQL Server判断语句(IF ...
    99+
    2023-06-20
  • linux shell内置判断语句的示例分析
    这篇文章主要介绍了linux shell内置判断语句的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。内置判断,成功的时候返回0,不成功返回非零  test ...
    99+
    2023-06-09
  • C语言的三种条件判断语句怎么使用
    本篇内容介绍了“C语言的三种条件判断语句怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!if语句if语句中,首先判断表达式的值,然后根...
    99+
    2023-06-29
  • C#解决多IfElse判断语句和Switch语句问题的方法分享
    这篇文章介绍使用设计模式中的策略模式和委托来解决多个IfElse判断语句和Switch语句,这种替换方式在其他语言也一样可以做到,比如PHP、JavaScript、Python或者J...
    99+
    2022-12-08
    C#多IfElse判断语句 C#多Switch语句 C# 策略模式
  • 计算机编程中常见的if语句是条件判断语句吗
    这篇文章主要介绍“计算机编程中常见的if语句是条件判断语句吗”,在日常操作中,相信很多人在计算机编程中常见的if语句是条件判断语句吗问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”计算机编程中常见的if语句是条...
    99+
    2023-07-05
  • Python判断和循环语句的分析与应用
    目录一、条件判断语句1、单纯的if语句2、if else语句3、if elif else语句二、循环语句while循环语句while语句while else语句for循环语句三、br...
    99+
    2022-11-11
  • C语言的三种条件判断语句你都了解吗
    目录if语句if的嵌套形式条件运算符switch语句switch多路开关模式总结if语句 if语句中,首先判断表达式的值,然后根据该值的情况控制程序流程。表达式的值不等于0,即为真;...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作