JPQL 查询 - 休眠:提取的关联不允许带子句

Pet*_*sky 14 java hibernate jpa join jpql

我有这样的 JPA 存储库和 JPQL 查询:

@Query("SELECT c from Campaign c" +
        " left join fetch c.postsList p on p.status = :postStatus" +
        " left join fetch p.platform" +
        " left join fetch c.campaignStatistics stat on stat.updateDate = :updateDate" +
        " where c.id =:id")
Campaign findCampaignWithPosts(
        @Param("id") Long id,
        @Param("postStatus") PostStatus postStatus,
        @Param("updateDate") LocalDate updateDate);
Run Code Online (Sandbox Code Playgroud)

但它不起作用。我得到:

org.hibernate.hql.internal.ast.QuerySyntaxException: with-clause not allowed on fetched associations; use filters
Run Code Online (Sandbox Code Playgroud)

我去研究了有关 JPA 2.1 规范的信息,这就是我发现的:

用于连接的连接条件来自映射的连接列。这意味着 JPQL 用户通常不必知道每个关系是如何连接的。在某些情况下,需要向连接条件附加附加条件,通常是在外部连接的情况下。这可以通过 ON 子句来完成。ON 子句在 JPA 2.1 规范中定义,并且某些 JPA 提供程序可能支持。EclipseLink : Hibernate : TopLink - 支持 ON 子句。

应该注意的是,这种类型的查询根本没有帮助我,因为在这个查询中有时我会得到空值,在连接表之后使用 where 子句。

   @Query("SELECT c from Campaign c" +
            " left join fetch c.postsList p" +
            " left join fetch p.platform" +
            " left join fetch c.campaignStatistics stat" +
            " where c.id =:id" +
            " and p.status = :postStatus" +
            " and stat.updateDate = :updateDate")
Run Code Online (Sandbox Code Playgroud)

在这种情况下该怎么办?除了如何使用本机查询之外,没有其他解决方案吗?但是几乎所有 JPQL 查询的含义都丢失了。我使用休眠版本 5.2.12

HL'*_*REB 10

您是对的,当您添加 p.status = :postStatus 时,它会过滤掉联接右侧不存在的结果(即,当 Campaign 没有帖子时)。

对我有用的是添加一个 OR 子句来接受连接右侧为 NULL 的情况。

所以,你应该替换and p.status = :postStatusand (p IS NULL OR p.status = :postStatus).

所以这个请求应该有效:

@Query("SELECT c from Campaign c" +
            " left join fetch c.postsList p" +
            " left join fetch p.platform" +
            " left join fetch c.campaignStatistics stat" +
            " where c.id =:id" +
            " and (p is NULL OR p.status = :postStatus)" +
            " and stat.updateDate = :updateDate")
Run Code Online (Sandbox Code Playgroud)

至于您收到的错误信息,我认为您不应该添加 ON条款,因为 JPA/Hibernate 已经处理了条款。

我正在使用 Hibernate 5.0.12。

  • [不是一个好主意](/sf/answers/407374201/) 在 `fetch` 别名上使用 `WHERE` 条件。 (2认同)

小智 7

没有替代解决方案,因为当你有这样的谓词时:

and (p is NULL OR p.status = :postStatus)
Run Code Online (Sandbox Code Playgroud)

然后出现3种情况:

  1. getPostsList() 返回空列表
  2. getPostsList() 返回至少包含一个具有查询状态的元素的列表
  3. getPostsList() 返回没有具有查询状态的元素的列表

在第 3 种情况下,您将完全丢失 Campaign 的所有行。但获取具有 1 个状态的

因为当 postList 的列表不为空时,左连接不会连接空值