现象
java项目中,连接mysql数据库,分为两种实现查询:1、xml配置sql;2、QueryWrapper拼接条件。
查询条件为
1 | IF(JSON_VALID(pl.extra_data), JSON_EXTRACT(pl.extra_data ,'$.servbigid') = #{requestDTO.servbigid},1=2) |
字段是一个json,里面包含一个key:servbigid,查询这个的值,如果高字段存储的有问题直接不返回结果。
1、xml配置sql:功能正常。
2、QueryWrapper拼接条件:报错ClassCastException
1 | Cause: java.lang.ClassCastException: net.sf.jsqlparser.expression.Function cannot be cast to net.sf.jsqlparser.schema.Column |
项目中报错,但是按照相同版本,本地搭建一个简易样例,一切正常。
解决
QueryWrapper无法解决,改变实现方式。
原因
ClassCastException 是 MyBatis-Plus 底层依赖的 JSQLParser 解析器 无法识别 IF(JSON_VALID(…), …, …) 这种嵌套函数写法导致的 —— 它误把 IF 函数当成了普通列(Column),从而触发类型转换错误,这是 MyBatis-Plus queryWrapper.apply() 解析复杂嵌套函数兼容性问题。
JSQLParser 是 MyBatis-Plus 用来解析 / 校验 SQL 语法的工具;
它对 IF(函数表达式, 条件表达式, 条件表达式) 这种 “非标准” 写法(即使原生 MySQL 支持)的解析逻辑不完善;
解析时把 IF(…) 这个函数(Function) 错误判定为列(Column),强行类型转换就抛出 ClassCastException。
简单说:不是SQL 逻辑错了,是 MyBatis-Plus 的解析器 “看不懂” 这种嵌套写法,和原生 MySQL 能跑不冲突。
正式项目中可能开启了 MyBatis-Plus 租户插件 / 数据权限插件 / 自定义 SQL 解析器,这些插件会对 apply() 中的所有 “函数表达式” 做强制的 “列归属校验”—— 哪怕是简单的 JSON_VALID(extra_data),也会被插件解析成 Function 类型,再强制转换为 Column 类型,最终触发报错。
这种场景下,任何基于 QueryWrapper 的写法都无法解决,因为插件会拦截所有 Wrapper 生成的 SQL 并做解析校验,唯一出路是跳过 Wrapper,直接写原生 SQL。