将空列表作为参数传递给JPA查询会引发错误

Tuu*_*nen 28 java persistence hibernate jpa list

如果我将空列表传递给JPA查询,我会收到错误.例如:

List<Municipality> municipalities = myDao.findAll();  // returns empty list
em.createQuery("SELECT p FROM Profile p JOIN p.municipality m WHERE m IN (:municipalities)")
    .setParameter("municipalities", municipalities)
    .getResultList();
Run Code Online (Sandbox Code Playgroud)

因为列表是空的,所以Hibernate在SQL中将其生成为"IN()",这使我在Hypersonic数据库中出错.

Hibernate问题跟踪中有一个这样的票,但那里没有很多评论/活动.我不知道其他ORM产品或JPA规范中的支持.

我不喜欢每次都必须手动检查空对象和空列表的想法.是否有一些众所周知的方法/扩展?你如何处理这些情况?

Pas*_*ent 36

根据JPA 1.0规范中的4.6.8表达式:

逗号分隔列表中必须至少有一个元素定义IN表达式的值集.

换句话说,无论Hibernate能够解析查询并传递一个IN(),无论特定数据库支持这种语法(PosgreSQL不根据Jira问题),如果你想要你的话,你应该在这里使用动态查询代码是可移植的(我通常更喜欢使用Criteria API进行动态查询).

  • 使用 *Spring Data*: 而不是传递一个空列表,传递 `null`。它将评估为假。 (4认同)

r_d*_*yas 10

假设 SQL 查询类似于

(COALESCE(:placeHolderName,NULL) IS NULL OR Column_Name in (:placeHolderName))
Run Code Online (Sandbox Code Playgroud)

现在,如果 List 是 String 类型,那么您可以传递为

query.setParameterList("placeHolderName", 
!CollectionUtils.isEmpty(list)? list : new ArrayList<String>(Arrays.asList("")).
Run Code Online (Sandbox Code Playgroud)

如果列表包含整数值,则语法如下所示:

If(!CollectionUtils.isEmpty(list)){
query.setParameterList("placeHolderName",list)
}else{
query.setParameter("placeHolderName",null, Hibernate.INTEGER)
}

Run Code Online (Sandbox Code Playgroud)

  • 你可以只写“COALESCE(:placeHolderName)”而不是“COALESCE(:placeHolderName,NULL)” (2认同)

小智 7

我也在这个问题上挣扎。我发现 Hibernate 社区已经解决了Hibernate 版本 5.4.10 中的问题,这是票证:https : //hibernate.atlassian.net/browse/HHH-8091

您可以检查您的 Hibernate 版本 System.out.println(org.hibernate.Version.getVersionString());

您可以将 Hibernate 的版本更新到最新版本,这是一个有用的链接:https : //hibernate.org/orm/releases/


小智 7

我今天遇到了同样的问题,@r_divyas 的回复几乎为我解决了这个问题,但我必须做一个小的改变才能使其工作。

我有一个查询保存在数据库中,因此无法即时更改它。该查询根据结果集中的字段触发动态 UI 的构建。

在用户界面中,我有一个多项选择下拉菜单,这是可选的。所以从中可以选择0个、1个或者多个元素。

因此,我需要找到一种方法使该参数在我的查询中可选。最初,我将其设置为:

(:assignedUsers IS NULL OR wr.USR_ID IN (:assignedUsers))

不幸的是,这仅适用于空参数或单个元素的列表。在设计时,我没有使用列表中的多个元素对其进行测试。当我最终到达那里时,我遇到了以下错误:

SQL Error [4145] [S0001]: An expression of non-boolean type specified in a context where a condition is expected, near ','.

这是由以下代码引起的:

AND (('id1', 'id2', 'id3') IS NULL OR wr.USR_ID IN ('id1', 'id2', 'id3'))

然后我尝试了他的解决方案,当我的列表不为空或为空时,该解决方案确实有效。但当它出现时,查询变成了这样:

AND (COALESCE('', NULL) IS NULL OR wr.USR_ID IN (''))

这导致结果集为空。

现在,继续我找到的解决方案。我所要做的就是更改查询中的条件:

AND (COALESCE(:assignedUsers, NULL) = '' OR wr.USR_ID IN (:assignedUsers))

这适用于空列表、空值、具有单个或多个元素的列表。