Why MyBatis Treats Integer 0 as an Empty String in <if> Conditions

When using MyBatis dynamic SQL to filter records by a numeric state field, the framework incorrectly evaluates the condition "state != ''" as false for the integer value 0 because its OGNL expression evaluator treats 0 as equivalent to an empty string, leading to unexpected query results.

Architecture Digest
Architecture Digest
Architecture Digest
Why MyBatis Treats Integer 0 as an Empty String in <if> Conditions

Problem

A MyBatis mapper uses a dynamic <if> clause to filter rows by a state column:

<if test="req.state != null and req.state != ''">
    AND md.state = #{req.state}
</if>

The front‑end sends state as an Integer (0 or 1). When req.state is 0, the condition is evaluated as false and the state filter is omitted, causing incorrect query results.

Root Cause

MyBatis evaluates the test attribute with OGNL. In OGNL, numeric values are converted to BigDecimal and considered true only if they are non‑zero. The expression state != '' forces OGNL to compare an Integer with an empty string, which results in the integer being treated as false when its value is 0. Consequently the whole expression state != null and state != '' evaluates to false for 0.

MyBatis Internals

The parsing flow is:

private void initNodeHandlerMap() {
    nodeHandlerMap.put("if", new IfHandler());
    // other handlers omitted
}
IfHandler

creates an IfSqlNode that stores the test string and delegates evaluation to ExpressionEvaluator:

public class IfHandler implements NodeHandler {
    public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) {
        MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle);
        String test = nodeToHandle.getStringAttribute("test");
        IfSqlNode ifSqlNode = new IfSqlNode(mixedSqlNode, test);
        targetContents.add(ifSqlNode);
    }
}

The IfSqlNode applies the expression:

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

Key part – ExpressionEvaluator.evaluateBoolean:

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;
}

When the expression is state != null and state != '' and state = 0, OGNL evaluates the second part as false, making the whole test false.

Reproduction

Add OGNL dependency and run a simple test:

<dependency>
    <groupId>ognl</groupId>
    <artifactId>ognl</artifactId>
    <version>2.7.3</version>
</dependency>

public static void main(String[] args) {
    Map<String, Object> map = new HashMap<>();
    map.put("state", 0);
    Object result = OgnlCache.getValue("state != null and state != ''", map);
    System.out.println(result); // prints false
}

The program prints false, confirming the OGNL behaviour.

Solution

Do not compare numeric parameters with an empty string. Typical fixes are:

Remove the empty‑string check:

<if test="req.state != null">
    AND md.state = #{req.state}
</if>

Explicitly handle zero:

<if test="req.state != null and req.state != 0">
    AND md.state = #{req.state}
</if>

Either approach ensures that a legitimate 0 value is not filtered out.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javaMyBatisbugOGNLDynamic SQLInteger Comparison
Architecture Digest
Written by

Architecture Digest

Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.