如何将原生Native Query转换为JPQL并解决JPA查询语法报错问题
错误原因与修改方案
具体错误点
- 语法错误:HAVING子句中
sum(det.cantidad<=1)写法不符合JPQL规范,聚合函数SUM()的入参应为可求和的数值字段,判断逻辑需要在求和完成后执行。结合业务规则,正确写法为SUM(det.cantidad) >= 1,即只要该客户今日购买该商品的总数量达到1,就属于需要排除的商品。 - 子查询返回值不匹配:
NOT IN运算符要求子查询返回和匹配字段p.idProducto类型一致的集合,原语句子查询返回c.detalles(订单明细实体集合),需要修改为返回订单明细关联的商品ID。 - 条件匹配类型错误:入参是客户ID,原条件
c.cliente=?1是拿客户实体和ID数值比较,类型不匹配,需要调整为匹配客户实体的主键字段。 - 属性名匹配错误:JPQL中使用的是Java实体类的属性名,而非数据库表字段名,若原语句中的
det.id_producto是数据库列名,需要替换为对应实体的属性名。
修改后的代码
@Query("SELECT p FROM Producto p WHERE p.idProducto NOT IN " + "(SELECT det.producto.idProducto FROM Compra c " + "JOIN c.detalles det " + "WHERE c.cliente.idCliente = ?1 AND DATE(c.fecha) = CURRENT_DATE() " + "GROUP BY det.producto.idProducto " + "HAVING SUM(det.cantidad) >= 1)") List<Producto> getProductosHabilitadosPorCliente(int idCliente);
上述语句逻辑为:先查询指定客户当日所有订单中累计购买数量≥1的商品ID集合,再查询不在该集合内的所有商品,即符合该客户当日可购买规则的商品。
注意:请根据你项目的实际实体字段命名调整关联属性名,比如
Detalle实体中关联Producto的字段如果不是producto、Cliente实体的主键如果不是idCliente,请对应修改为实际属性名即可。
内容的提问来源于stack exchange,提问作者Eric Unzué Madueña
相关产品推荐
相关产品推荐

