【问题标题】:Handling null parameters in JPQL在 JPQL 中处理空参数
【发布时间】:2015-02-09 00:57:03
【问题描述】:

我刚刚意识到当任何参数为空时,JPQL where 子句无法按预期工作。 例如这个简单的 JPQL 查询

SELECT en FROM Entity en WHERE en.name = :name

name 参数为 null 时不返回任何结果,即使数据库中存在名称设置为 null 的实体。

在这种情况下,Hibernate 使用WHERE entity.NAME = null 执行 SQL。显然这不是由数据库处理的,因为标准定义了IS NULL 用于空比较(参见SQL is null and = null)。 JPQL 也有 IS NULL 运算符(http://docs.oracle.com/javaee/6/tutorial/doc/bnbuf.html#bnbvi),其行为与 SQL(http://docs.oracle.com/javaee/6/tutorial/doc/bnbuf.html#bnbvr)中的行为完全相同。

我认为这是一个常见的情况,但快速搜索并没有给我任何有趣的结果。

那么,有没有办法在查询中包含空值? 到目前为止,我想出了以下内容:

SELECT en FROM Entity en WHERE (:name IS NULL AND en.name IS NULL) OR en.name = :name

它工作正常,但看起来并不优雅,尤其是在较大的查询中。

额外问题:为什么 JPQL 模仿 SQL 的这个奇怪方面?

【问题讨论】:

  • 因为同样的原因,oracle 使用 null 而不是 =null。 docs.oracle.com/cd/B19306_01/server.102/b14200/…
  • 同样的事情也适用于没有 ORM 框架的工作。让我们有一个 SQL 语句,例如 - SELECT * FROM table_name WHERE column_name=:name。如果绑定命名参数的值为null,那么语句不会神奇地改变以自动反映IS NULL 条件。不是吗?
  • 除了这是 JPQL 不是 SQL,因此实现完全有能力相应地决定其 SQL 并且应该能够应对。
  • 您的解决方案仍然是一个很好的答案

标签: java hibernate jpa jpql


【解决方案1】:

并非所有 JPA 实现都会将带有 name 参数的 en.name = :name 转换为 nullentity.NAME = null。例如,我使用的实现(DataNucleus JPA)将其转换为entity.NAME IS NULL IIRC。

JPQL 不会告诉实现要执行什么 SQL,只是用户可以定义什么。其余的由实施决定。由用户决定使用哪个实现。

【讨论】:

  • 感谢您的回答。不幸的是,我不能简单地将 Hibernate 更改为其他 JPA 实现。此外,在我的选项中,DataNucleus 不完全符合 JPA 标准。 docs.oracle.com/javaee/6/tutorial/doc/bnbuf.html#bnbvr 声明“两个 NULL 值不相等。比较两个 NULL 值会产生一个未知值。”
  • 据我记得,当空参数是一个选项时,他们用于“IS NULL”的自动转换,如果他们愿意,人们可以直接使用参数文字。所以合规性不是问题(而且不是我所有的使用)。此外,它们还支持“其他”数据存储,并且某些 SQL92 约定在这些数据存储中没有意义,但“IS NULL”确实如此。
猜你喜欢
  • 1970-01-01
  • 2017-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-13
  • 1970-01-01
  • 2021-06-28
  • 1970-01-01
相关资源
最近更新 更多