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 astrue, zero asfalse; 数字类型的0或者是浮点类型的0.0都会被解析为false - If the object is a
Character, its boolean value istrueif and only if its char value is non-zero; - Otherwise, its boolean value is
trueif and only if it is non-null.
