Spring Boot3升级QueryDSL5.0.0后Enum查询SQL语法报错
Spring Boot 3.x + QueryDSL 5.0.0 升级后 select 中条件表达式导致 MySQL 语法错误
问题根源
从错误日志能看到,QueryDSL 生成的 SQL 把 product.stockStatus.eq(StockStatus.AVAILABLE) 直接转换为 p1_0.stockStatus=cast(? as smallint) 并放到了 select 列列表里。MySQL 不支持这种直接将比较表达式作为查询列的写法,这就是语法错误的核心原因。旧版本 QueryDSL/Spring Boot 可能隐式做了兼容处理,但升级到 5.x/3.x 后这个逻辑被调整了。
解决方案
需要把这个条件表达式转换成 MySQL 能识别的合法列表达式,推荐两种实现方式:
方案1:使用 Case 表达式(直观易读)
public List<ProductMiniResource> getAllProductsByProductCode(String[] productCodes) { return from(product) .where(product.code.in(productCodes) .and(product.status.eq(ProductStatus.ACTIVE))) .select(new QProductMiniResource(product.id, product.code, product.name, product.logoPath, // 用case表达式生成合法的布尔值列 Expressions.cases() .when(product.stockStatus.eq(StockStatus.AVAILABLE)).then(true) .otherwise(false), product.productRedirectUrl, product.displayName, product.inquiryType, product.allowReminder, product.allowSchedulePayment, product.allowSavePayment)) .fetch(); }
方案2:使用 booleanTemplate 直接定义 SQL 片段
public List<ProductMiniResource> getAllProductsByProductCode(String[] productCodes) { return from(product) .where(product.code.in(productCodes) .and(product.status.eq(ProductStatus.ACTIVE))) .select(new QProductMiniResource(product.id, product.code, product.name, product.logoPath, // 直接指定MySQL支持的表达式格式 Expressions.booleanTemplate("{0} = {1}", product.stockStatus, StockStatus.AVAILABLE), product.productRedirectUrl, product.displayName, product.inquiryType, product.allowReminder, product.allowSchedulePayment, product.allowSavePayment)) .fetch(); }
说明
两种方案都会生成 MySQL 可识别的合法 SQL:Case 表达式会被转换为 case when p1_0.stock_status = ? then 1 else 0 end,booleanTemplate 则直接生成等价的合法比较表达式,最终都能正确返回布尔值对应的结果。
内容的提问来源于stack exchange,提问作者Milan Paudyal
相关产品推荐
相关产品推荐

