我有一个想要运行的复杂 HQL 查询。我的参数之一是
Set<Integer>
,其结果具有有效值
类似:
select * from table t where t.code IN (Set<Integer>)
这很简单吧?问题是我希望这个查询返回所有项目,如果
Set<Integer>
为空或为空(不需要为空或为空,任何一种情况都足够)
考虑JPA存储库方法:
public Page<Table> findAll(@Param("codes") Set<Integer> codes);
我尝试了几种方法:
SELECT t FROM table t where :codes IS NULL OR t.code IN (:codes)
运行时错误:
SQL Error: 1241, SQLState: 21000 (conn=3123) Operand should contain 1 column(s)
SELECT t FROM table t where (:codes) IS EMPTY OR t.code IN (:codes)
spring 甚至无法启动
??? is not mapped
从表 t 中选择 t,其中 size((:codes)) = 0 OR t.code IN (:codes)
还有许多其他
是否有一种通用方法可以进行此检查并使此查询正常工作而无需动态构建查询?
您应该使用
Specification
来代替,并使用 JPA Criteria API 有条件地将谓词添加到 where 子句。这样,您的查询计划将比使用此通用解决方案更好,此外它也不会使用意外起作用的东西。请注意,此查询 SELECT t FROM table t where COALESCE(:codes) IS NULL OR t.code IN (:codes)
将不再适用于 Hibernate 6。
不是最好的答案,但我在 stackoverflow 上找到了解决方案 https://stackoverflow.com/a/54035166/5679560
解决方案是除了 IS NULL 之外简单地使用 COALESCE,这样它就可以处理多个值。
SELECT t FROM table t where COALESCE(:codes) IS NULL OR t.code IN (:codes)
你的数组应该由原始类型组成,以便 hql 正确地比较每个数组
在你的伪代码示例中,而不是
select * from table t where t.code IN (Set<Integer>)
应该是
select * from table t where t.code IN (int[])