输入参数集合包含 null 的 JPQL 查询

Posted

技术标签:

【中文标题】输入参数集合包含 null 的 JPQL 查询【英文标题】:JPQL query with input parameter collection containing null 【发布时间】:2021-11-21 13:15:36 【问题描述】:

我需要在以下 JPQL 查询中通过 IN 表达式比较可为空的实体属性:

@NamedQuery(name = "query",
        query = "SELECT e FROM MyEntity e WHERE e.status IN :statuses")

现在,我喜欢显示的集合值输入参数 statuses 可以选择包含null 作为元素:

final List<MyEntity> actual = entityManager.createNamedQuery("query", MyEntity.class)
            .setParameter("statuses", Arrays.asList(null, 1L))
            .getResultList();

但是,对于 Hibernate/Derby,实际结果列表仅包含状态为 1L 而不是 null 的实体。

我在 JPA 2.2 规范中没有找到关于这个案例的任何内容。是我遗漏了什么还是这个供应商特定的?


this question 的答案只能解决我的部分问题。在他们提出的解决方案中,null 比较被硬生化到查询中,无法通过集合值参数进行控制。

【问题讨论】:

这能回答你的问题吗? Checking for NULL on a Collection in JPQL queries? @Yann39 谢谢,我也发现了这个问题。但是,答案只能解决我的部分问题。在他们提出的解决方案中,null 比较被硬生化到查询中,并且无法通过集合值参数进行控制。 【参考方案1】:

作为一名 Java 程序员null = null 产生 true 可能会让人感到惊讶,在 SQL(和 JPQL)中,null = null 本身就是 null,这是“虚假的”。因此,null in (null) 也会产生 null。

相反,您需要单独处理 null 并使用 IS NULL 检查:e.status IS NULL OR e.status IN :statuses

这在 JPA 规范的 4.11 空值中有描述:

具有 NULL 值的比较或算术运算总是产生未知值。 两个 NULL 值不相等,比较会产生一个未知值。

【讨论】:

谢谢,这很有道理。我确实对这里的 ORM 世界有不同的期望,但是 JPQL 不能修改 SQL 的语义。对于我的具体情况,这意味着我需要引入两个相应的 JPQL 查询(一个带有... IS NULL OR ...,另一个没有)并在 Java 端决定调用哪一个,对吗? 是的,恐怕是这样!

以上是关于输入参数集合包含 null 的 JPQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

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

使用 JPQL 从实体的元素集合中删除

JPQL:在构造函数表达式中接收集合

将 SQL(不是 JPQL)映射到简单 Java 对象的集合?

JPQL IN 子句:Java 数组(或列表、集合...)?

MYSQL查询--聚合函数查询