mybatis中的if-test判断坑

电脑杂谈  发布时间:2020-05-14 16:09:43  来源:网络整理

c 嵌套类_笔记本产品a类b类c类_结构体类型的定义允许嵌套是指

【test =“ takeWay =='0'”>},如果判断是mybatis

单个字符必须用双引号引起来. 更改为或更改为

.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”错误,导致在判断时未执行sql,运行程序未报告错误,没有提示. 删除takeWay ==“ 1”并执行. 我对此感到困惑,

因为我写了下面的代码,所以是真的.

结构体类型的定义允许嵌套是指_笔记本产品a类b类c类_c 嵌套类

<if test="messageType == 'senderReceiveSuccess' ">
      ......
</if>

参加

更改为

或更改为.

原因是: mybatis被OGNL表达式解析. 在OGNL表达式中,“ 1”将被解析为字符,java将被强类型化,char和字符串将导致不平等,因此,如果标记sql in将不会被解析.

用法摘要: 单个字符必须用双引号引起来或使用.toString()!

c 嵌套类_结构体类型的定义允许嵌套是指_笔记本产品a类b类c类

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

POJO

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

地图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>

当状态值为0时,通常不会对SQLand status = 0进行拼接,即测试中的表达式为false,这会导致查询结果不正确. 但是,显然是该值(整数: 0)! = null也! =”,应该是真的.

c 嵌套类_结构体类型的定义允许嵌套是指_笔记本产品a类b类c类

当status为Integer类型且status值为0时,if判断为假.

状态为0时,Mybatis将解析为''空字符串.

为避免此问题,请将其更改为如下所示,并删除对空字符的判断以解决该问题

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

原因分析

通过Debug MyBatis源代码,我找到了IfSqlNode类,该类用于处理动态SQL 节点,而public boolean apply方法(DynamicContext上下文)用于在该节点中构造SQL语句. if(evaluator.evaluateBoolean(test,context.getBindings())此代码是解析测试中的表达式的键,如果表达式为true,则stitch SQL,否则忽略.

结构体类型的定义允许嵌套是指_c 嵌套类_笔记本产品a类b类c类

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类c 嵌套类,然后发现解析的表达式使用OGNL. 如果您使用了古老的Struts框架,则应该熟悉它. 通过OgnlCache.getValue(表达式,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;  
  }  

跟进看看,最后找到了一种解析表达式的方法,该方法是私有静态Object parseExpression(字符串表达式),该方法将首先从缓存中获取值,如果没有,它将被解析并放入缓存,然后调用Ognl.getValue(parseExpression(表达式),根)获取表达式的值.

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(表达式),根)的工作方式c 嵌套类,如果您有兴趣,可以跟进并查找,本文不再赘述. 到目前为止,我们已经知道MyBatis表达式是使用OGNL处理的,这就足够了. 让我们转到OGNL官方网站,看看我们的表达式语法是否存在问题,并且会发生此问题.

任何需要布尔值的对象都可以使用. OGNL将对象解释为布尔值,如下所示:

果然,如果对象是数字类型,则当值是0时,它将被解析为false,否则为true,浮点类型为0.00. OGNL的布尔值定义类似于JavaScript,即''== 0 == false. 这并不难理解并且status =#{status} 当status = 0,显然是0时出现的问题! =''不正确,导致表达式为假.

将表达式修改为和status =#{status} 将解决问题. 此问题的根本原因是来自非标准编码,仅需要判断String类型! =”,完全不需要其他类型. 可能是开发人员直接复制了前一行以保存更改,或者使用的MyBatis生成工具不够严格,从而导致了此问题.

如果您有类似String str =“ A”的文字,则有必要在此处提及另一个“坑”; 请小心. 因为如果它是单引号中的单个字符,则OGNL会将其识别为Java中的char类型. 显然,String类型和char类型的==操作将返回false,导致表达式不为true. 解决方案非常简单,只需将其修改为.


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-209989-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      • 卢滑滑
        卢滑滑

        侦察机配合驶往关岛12海里以内侦查

      • 周家华
        周家华

        严厉打击美国的挑衅行为

      • 王晨庆
        王晨庆

        但实际利率上浮不再设上限

      热点图片
      拼命载入中...