JPQL 查询 - 休眠:在提取的关联上不允许使用 with 子句

2022-09-04 02:58:37

我有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);

但它是行不通的。我得到:

org.hibernate.hql.internal.ast.QuerySyntaxException: with-clause not allowed on fetched associations; use filters

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

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

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

   @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")

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


答案 1

你是对的,当你添加和p.status = :p ostStatus时,它会过滤掉连接右侧不存在的结果(即当广告系列没有帖子时)。

对我有用的是添加一个 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")

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

我正在使用Hibernate 5.0.12。


答案 2

没有其他解决方案,因为当您有这样的谓词时:

and (p is NULL OR p.status = :postStatus)

然后出现3个案例:

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

在3种情况下的状态下,您将完全丢失广告系列的所有行。但是获取具有1个状态的

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


推荐