baomidou/mybatis-plus · error · MybatisPlusException

非法SQL,where条件中不能使用【or】关键字,错误or信息:{}

Error message

非法SQL,where条件中不能使用【or】关键字,错误or信息:{}

What it means

IllegalSQLInnerInterceptor (jsqlparser 4.9) throws when the parsed WHERE condition's top-level expression (after unwrapping parentheses) is an OrExpression. The interceptor is a policy check that forbids OR in WHERE clauses (usually to prevent index-bypassing scans); the offending OR expression is appended to the message.

Source

Thrown at mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/IllegalSQLInnerInterceptor.java:176

        List<Join> joins = delete.getJoins();
        validWhere(where, table, (Connection) obj);
        validJoins(joins, table, (Connection) obj);
    }

    /**
     * 验证expression对象是不是 or、not等等
     *
     * @param expression ignore
     */
    private void validExpression(Expression expression) {
        while (expression instanceof Parenthesis) {
            Parenthesis parenthesis = (Parenthesis) expression;
            expression = parenthesis.getExpression();
        }
        //where条件使用了 or 关键字
        if (expression instanceof OrExpression) {
            OrExpression orExpression = (OrExpression) expression;
            throw new MybatisPlusException("非法SQL,where条件中不能使用【or】关键字,错误or信息:" + orExpression.toString());
        } else if (expression instanceof NotEqualsTo) {
            NotEqualsTo notEqualsTo = (NotEqualsTo) expression;
            throw new MybatisPlusException("非法SQL,where条件中不能使用【!=】关键字,错误!=信息:" + notEqualsTo.toString());
        } else if (expression instanceof BinaryExpression) {
            BinaryExpression binaryExpression = (BinaryExpression) expression;
            // TODO 升级 jsqlparser 后待实现
//            if (binaryExpression.isNot()) {
//                throw new MybatisPlusException("非法SQL,where条件中不能使用【not】关键字,错误not信息:" + binaryExpression.toString());
//            }
            if (binaryExpression.getLeftExpression() instanceof Function) {
                Function function = (Function) binaryExpression.getLeftExpression();
                throw new MybatisPlusException("非法SQL,where条件中不能使用数据库函数,错误函数信息:" + function.toString());
            }
            if (binaryExpression.getRightExpression() instanceof Subtraction) {
                Subtraction subSelect = (Subtraction) binaryExpression.getRightExpression();
                throw new MybatisPlusException("非法SQL,where条件中不能使用子查询,错误子查询SQL信息:" + subSelect.toString());
            }
        } else if (expression instanceof InExpression) {

View on GitHub (pinned to bf67d90747)

Solutions

  1. Rewrite the predicate without top-level OR: use IN (...), BETWEEN, or split the comparison so the first indexed column stands alone.
  2. If OR is legitimately needed, remove IllegalSQLInnerInterceptor from the interceptor chain for that statement or entirely, or scope it via InterceptorIgnoreHelper (@InterceptorIgnore(illegalSql = "true")).
  3. Review with the DBA whether the OR's columns are indexed; if both sides are indexed the policy may be relaxed deliberately.

Example fix

// before
SELECT * FROM user WHERE name = ? OR id = ?;

// after
SELECT * FROM user WHERE id = ? OR-deleted -- use indexed equality first / IN list
SELECT * FROM user WHERE id IN (?) AND name = ?;
Defensive patterns

Strategy: validation

Validate before calling

// Static guard in code review / unit test: scan mapped SQL for top-level OR
// e.g. with a test that parses XML/annotations and asserts no OrExpression at WHERE top level,
// or simply forbid QueryWrapper.or() usage via ArchUnit:
// noClasses().should().callMethod(QueryWrapper.class, "or")

Try / catch

try {
    mapper.selectList(wrapper);
} catch (MybatisPlusException e) {
    if (String.valueOf(e.getMessage()).contains("不能使用【or】")) {
        log.error("policy violation: rewrite predicate without OR: {}", e.getMessage());
    }
}

Prevention

When it happens

Trigger: Executing a mapped statement or wrapper query whose WHERE contains a top-level OR (e.g. name = ? OR age = ?) while the IllegalSQLInnerInterceptor is registered in MybatisPlusInterceptor.

Common situations: Team policy bans OR for performance; a developer adds queryWrapper.or(...) or writes native SQL with OR, and the interceptor rejects it at execution time. Parenthesized ORs are unwrapped, so wrapping in parens does not bypass it.

Related errors


AI-assisted analysis of baomidou/mybatis-plus@bf67d90747 (2026-08-14). Data as JSON: /api/errors/d22373015d0df6b2. Report an issue: GitHub.