【问题标题】:Hibernate JPA: 'IS EMPTY' condition doesn't work for collections passed as parametersHibernate JPA:“IS EMPTY”条件不适用于作为参数传递的集合
【发布时间】:2018-06-25 06:54:42
【问题描述】:

我正在尝试编写一个查询,我需要在其中检查集合是否作为参数传递为空

我正在写这样的东西:

@Query("SELECT u FROM User u" +
        "WHERE" +
        "   :ids IS EMPTY" +
        "   OR u.id IN :ids")
Collection<User> findUsers(@Param("ids") Collection<String> ids);

此代码在启动时以QuerySyntaxException: ??? is not mapped 失败。堆栈跟踪没有提供任何有价值的信息,但我发现如果我删除下一部分:

:ids IS EMPTY

它开始工作了。

问:如何使用IS EMPTY查询参数?或者如何以任何其他方式检查集合是否为空?

注意:

  • 我使用的是 Spring Boot 1.5.8.RELEASE。
  • 我还查看了 "Passing empty list as parameter to JPA query throws error",这与以往不同,但没有帮助。
  • 我发布的代码很原始,只是为了说明目的而添加的,我的实际查询非常复杂,我真的需要检查集合是否为空。

【问题讨论】:

  • 您可以像这样使用find..In Collection&lt;User&gt; findByIdIn(@Param("ids") Collection&lt;String&gt; ids); 它适用于空参数
  • 如果这没有帮助你可以在这里查看@davidxxx 的答案stackoverflow.com/a/48073370/5558072
  • 如果我记得很清楚,IS EMPTY 用于 HQL 查询中的字段引用,而不是参数,例如u.someList IS EMPTY
  • @YCF_L 看到这只是一个例子,我非常复杂的查询,我真的需要检查是否为空。
  • 更正:您的意思是“不适用于 Hibernate JPA”,因为它适用于我尝试过的 JPA 提供程序(DataNucleus JPA)。您应该报告您的提供商的错误

标签: java hibernate jpa spring-boot spring-data-jpa


【解决方案1】:

在您的查询中,您要求数据库检查 :ids 的值,这不是数据库中的列,而是 Java 程序中的集合。

因此,持久性框架自然不知道您在说什么,并告诉您“...未映射”,这是真的。

我认为您可能想要以下查询:

@Query("SELECT u FROM User u" +
    "WHERE" +
    "   u.id IS NULL" +
    "   OR u.id IN :ids")

如果不是这样,请描述您希望通过查询实现的目标。

【讨论】:

  • 不,我需要不同的。条件u.id IN :ids 应该只适用于ids 不为空(如果ids 为空则被视为真——就像我在问题中发布的那样)
  • 如果:ids 是真的?你是什​​么意思?您的评论无法编译:P
  • @Repoker 如果ids 为空,我需要返回所有行忽略u.id IN :ids
  • 从持久性的角度来看没有意义,请寻找 @dognose 答案以获得解释
  • @OleksandrShpota 您不能在 SQL 查询中引用任何不属于数据库层的内容。您可以编写另一种不带参数的方法 findUsers() 来返回所有用户,并在集合为空时从外部上下文中调用该方法。
【解决方案2】:

JPA 文档明确指出,您应该避免将空集合作为参数。

4.6.8 在 JPA 1.0 规范中的表达式

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

如果您考虑一下,JPA 对此无能为力。如果查询包含WHERE id in ?0 - 如何处理空集合? WHERE id in () 是无效的语法,WHERE id in... 所以它需要删除整个 where-constraint,这在大多数情况下是不需要的。

猜你需要在你的应用程序中而不是在查询级别处理这个问题。

Side-Node:如果您正在使用只有很少选项的过滤器值,则可以通过添加所有 id 来获得结果,如果用户没有选择某些东西,即

where color_id in (1,2,..,10) and type_id in (1,2,3) AND tile_id in (1,2,..,5)
instead of the invalid
where color_id in () and type_id in () AND tile_id in ()

如果您有数千个选项,则无法正常工作,否则您将超出查询长度。

【讨论】:

    猜你喜欢
    • 2012-07-18
    • 2014-02-03
    • 1970-01-01
    • 2011-03-20
    • 1970-01-01
    • 2016-07-07
    • 2011-11-02
    • 2011-07-26
    • 1970-01-01
    相关资源
    最近更新 更多