喵星之旅-屯粮的松鼠-Wrapper对于复杂条件报错

现象

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
2
3
4
5
6
7
8
Cause: java.lang.ClassCastException: net.sf.jsqlparser.expression.Function cannot be cast to net.sf.jsqlparser.schema.Column
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:92)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:440)
at com.sun.proxy.$Proxy148.selectList(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:223)
at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.executeForIPage(MybatisMapperMethod.java:122)
at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:87)
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:148)

项目中报错,但是按照相同版本,本地搭建一个简易样例,一切正常。

解决

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。

文章目录
  1. 现象
  2. 解决
  3. 原因
|