baomidou/mybatis-plus · error · MybatisPlusException

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

Error message

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

What it means

Thrown by IllegalSQLInnerInterceptor.validExpression when the WHERE expression is a NotEqualsTo node. The interceptor's SQL standard forbids != (and <>) in WHERE because inequality comparisons generally cannot use a b-tree index efficiently; the offending expression is appended after '错误!=信息:'.

Source

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

    }

    /**
     * 验证expression对象是不是 or、not等等
     *
     * @param expression ignore
     */
    private void validExpression(Expression expression) {
        while (expression instanceof ParenthesedExpressionList) {
            ParenthesedExpressionList<Expression> parenthesis = (ParenthesedExpressionList) expression;
            expression = parenthesis.get(0);
        }
        //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) {
            InExpression inExpression = (InExpression) expression;
            if (inExpression.getRightExpression() instanceof Subtraction) {
                Subtraction subSelect = (Subtraction) inExpression.getRightExpression();

View on GitHub (pinned to bf67d90747)

Solutions

  1. Invert the condition into an explicit allow-list: WHERE deleted != 1 becomes WHERE deleted = 0 (or deleted IN (allowed values))
  2. Use NOT IN with the enumerated remaining values if the domain is small and fixed
  3. Remove or disable IllegalSQLInnerInterceptor if inequality filters are required by the domain

Example fix

// before (MyBatis-Plus wrapper)
new QueryWrapper<User>().ne("deleted", 1);
// after
new QueryWrapper<User>().eq("deleted", 0);
Defensive patterns

Strategy: try-catch

Validate before calling

// Detect != / <> predicates before execution
Expression where = ((PlainSelect) ((Select) CCJSqlParserUtil.parse(sql).getSelectBody()).getSelectBody()).getWhere();
if (where instanceof NotEqualsTo) {
    throw new IllegalArgumentException("!= / <> in WHERE blocked by IllegalSQLInnerInterceptor");
}

Type guard

static boolean isNotEquals(Expression where) {
    return where instanceof NotEqualsTo;
}

Try / catch

try {
    return mapper.findActive();
} catch (MybatisPlusException e) {
    if (e.getMessage() != null && e.getMessage().contains("【!=】")) {
        return mapper.findActiveByIn(); // equality allow-list variant
    }
    throw e;
}

Prevention

When it happens

Trigger: Executing WHERE col != value or WHERE col <> value through a MybatisPlusInterceptor chain containing IllegalSQLInnerInterceptor; also QueryWrapper.ne(...) generated SQL.

Common situations: Filter-out logic (e.g. WHERE deleted != 1, WHERE status != 'CANCELLED') in existing mappers; teams adopting the interceptor later and discovering widespread .ne() usage in wrappers.

Related errors


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