JPQL查询 - hibernate:在获取的关联上不允许使用with子句

时间:2017-11-29 01:34:02

标签: java hibernate jpa join jpql

我有这样的JPA Repository和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,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")

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

3 个答案:

答案 0 :(得分:3)

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

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

因此,您应该将and p.status = :postStatus替换为and (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")

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

我正在使用Hibernate 5.0.12。

答案 1 :(得分:1)

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

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

然后出现3个案例:

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

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

因为left join不会加入null,当postList的list不为空时

答案 2 :(得分:0)

not a good idea在获取别名

上使用WHERE条件

试试这个

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