代码之家  ›  专栏  ›  技术社区  ›  Sasha Shpota A-Bag

Hibernate JPA:“为空”条件不适用于作为参数传递的集合

  •  0
  • Sasha Shpota A-Bag  · 技术社区  · 7 年前

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

    我在写这样的东西:

    @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 查询参数?或者如何以任何其他方式检查集合是否为空?

    注:

    2 回复  |  直到 7 年前
        1
  •  2
  •   dognose    7 年前

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

    JPA 1.0规范表达式中的4.6.8

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

    如果你仔细想想,JPA对此无能为力。如果查询包含 WHERE id in ?0 -如何处理空集合? WHERE id in () 是无效语法,以及 WHERE id in ... 因此,需要删除整个where约束,这在大多数情况下都不是所希望的。

    我想您需要在应用程序中而不是在查询级别上处理这个问题。

    侧节点:如果您使用的过滤器值只有很少的选项,那么如果用户没有选择某个内容,例如。

    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 ()
    

    如果您有数千个选项,就不能工作,否则将超过查询长度。

        2
  •  1
  •   Kirinya    7 年前

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

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

    我想您可能需要以下查询:

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

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