在 JPQL 查询中检查集合上的 NULL 吗?

Posted

技术标签:

【中文标题】在 JPQL 查询中检查集合上的 NULL 吗?【英文标题】:Checking for NULL on a Collection in JPQL queries? 【发布时间】:2017-12-23 04:14:10 【问题描述】:

我正在编写一个 JPQL 查询,该查询基于 Categories 集合进行查询。我的类别可以为空,因此我使用 :categories=NULL 进行检查。

@Query("Select v from Vendor v join v.org vorg join v.categories cats WHERE vorg.email =:email AND (cats in :categories or :categories = NULL)")
Set<Vendor> filterVendors(@Param("emailId") String emailId, @Param("categories") Set<Category> categories);

当 category 为 NULL 时,上述方法可以正常工作。但是,当类别超过一个值时,我会收到错误

java.sql.SQLException:操作数应包含 1 列

而hibernate相关的trace是

category6_.category_id in ( ? , ? ) 要么 ( ? , ? ) 一片空白 )

如何在 JPQL 中检查集合是否为空?我认为解决这个问题应该可以解决这个错误。任何帮助表示赞赏

谢谢。

【问题讨论】:

1-什么是 vorg.email vorg 不是别名。 2- :email 和 @param 定义名称为“emailId” 有一个小错字。现在更正了,希望现在很清楚。谢谢。 【参考方案1】:
Select v from Vendor v join v.categories cats WHERE vorg.email =:email AND (cats in :categories or cats IS EMPTY)

您可以使用IS [NOT] EMPTY 运算符来测试空集合。 JPA 不一定会带回 NULL 集合。想想看,DB返回的是一个空集合。

哦,我修正了你的查询(虽然我没有测试它)。

【讨论】:

我正在测试上述内容,并在集合发送为空时收到一些 SQL 语法错误。我很好奇,你为什么要测试猫是空的?我们不应该检查参数类别是否为空吗?? 因为cats 已经声明并分配给v.categories 抱歉,根据你的建议试了很多次,还是不行。【参考方案2】:

所以我被困在做一些非常相似的事情。基本上你想看看是否有

    您传入的集合是空的:那就不要在查询中包含它 您传入的集合已填充:然后将其包含在查询中

问题是没有很好的方法来处理这部分:

:categories = NULL

这是因为当翻译成 SQL 时,它看起来像这样(当集合中有 2 个项目时):

@p0, @p1 = NULL

也不能用括号括起来,因为这在 SQL 中无效:

(@p0, @p1) = NULL

我尝试使用 coalesce 将值减少到 NULL,但我也无法让它工作。

据我所知,JPQL 中没有任何内容可以让您运行某种集合(哈希集等)的函数来查看它是否已填充。如果有人知道,请告诉我们。

最后我使用了一个 hack,在调用代码中我检查了集合以查看它是否被填充。如果不是,我只需再传入一个参数……一个空字符串。

String catString = "";
if (categoryList != null && !categoryList.isEmpty()) catString = "HasCats";

然后在 JPQL 中执行以下操作:

WHERE (:catsString = '' or cats IN (:categories)) "

不是世界上最好的解决方案,但它很实用。

【讨论】:

是的,感谢您在将近一年后的努力中回答这个问题。明智的一年,我认为您提出的建议是唯一的方法-我使用类似的方法或使用参数列表很长的本机查询。 为了让它更干净一点,你可以使用 apache utils 或其他东西来做列表的 null 和 isEmpty 一次检查。就像您的 if 条件中的 CollectionUtils.isNotEmpty(categoryList) 一样。 apace utils 中的 isNotEmpty 方法将检查 null 和空条件。【参考方案3】:

我可以这样得到它:

coalesce(:myIdCollection, null) is null or id in (:myIdCollection)

【讨论】:

非常感谢。你拯救了我的一天。像魅力一样工作。 在我阅读的所有建议中,这是我尝试过的唯一一个有效的建议。谢谢! 您甚至不需要coalesce 函数中的硬编码null 值:coalesce(:myIdCollection) is null or id in (:myIdCollection) 应该可以完成这项工作。【参考方案4】:

如果使用 PostgreSQL 的人遇到这个问题,可以很容易地通过添加括号来解决:

(cats in :categories or (:categories) IS NULL)

【讨论】:

以上是关于在 JPQL 查询中检查集合上的 NULL 吗?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 JPQL 中检查 null ZonedDateTime?

我可以限制使用 JPQL 命名查询的 Spring Data 查询方法的查询结果吗?

在 JPQL 中可以选择 EXISTS() 吗?

枚举上的 JPQL LIKE 表达式

如何在 JPA JPQL 查询中加入两个实体集合?

带有枚举值的 jpql IN 查询