Back to Journal
02 / Entry· 1 min read

Mybatis动态SQL注意事项之if-test

test 数据判断之Int类型时且等于0时的问题

🔊 AI朗读

test 数据判断之Int类型时且等于0时的问题

html
<if test="dto.status != null and dto.status != ''">
    and `status` = #{dto.status,jdbcType=INTEGER}
</if>

当传入的数据是INTEGER类型时,传入非0数据的时候,是可以正常拼接sql and status = 1|2|-1|...,如果传入的数据是0的时候,这个时候if判断的结果就是false,不会拼接sqland status = 0语句。

具体原因是:

通过debug追踪之后,可以看到Mybatis中关于动态判断的if语句是被IfSqlNode这个类装配,test属性表达式的判断是apply()方法。

java
public class IfSqlNode implements SqlNode {
  private final ExpressionEvaluator evaluator;
  private final String test;
  private final SqlNode contents;

  public IfSqlNode(SqlNode contents, String test) {
    this.test = test;
    this.contents = contents;
    this.evaluator = new ExpressionEvaluator();
  }

  @Override
  public boolean apply(DynamicContext context) {
    if (evaluator.evaluateBoolean(test, context.getBindings())) {
      contents.apply(context);
      return true;
    }
    return false;
  }

}

继续追踪evaluator属性this.evaluator = new ExpressionEvaluator();可以看到调用它的这个方法evaluateBoolean()

java
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)).compareTo(BigDecimal.ZERO) != 0;
    }
    return value != null;
  }

进入这个方法发现OgnlCache这个类,getValue()方法中有一个ognl.Ognlmybatis这个地方使用了OGNL解析表达式

java
public static Object getValue(String expression, Object root) {
    try {
      Map context = Ognl.createDefaultContext(root, MEMBER_ACCESS, CLASS_RESOLVER, null);
      return Ognl.getValue(parseExpression(expression), context, root);
    } catch (OgnlException e) {
      throw new BuilderException("Error evaluating expression '" + expression + "'. Cause: " + e, e);
    }
  }

如下就是关于为什么会把0解析为false的具体原因了

https://commons.apache.org/proper/commons-ognl/language-guide.html

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数字类型的0或者是浮点类型的0.0都会被解析为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.
分享
← 返回博客列表
🎁 有邀请福利哦,点击查看
🎁