代码之家  ›  专栏  ›  技术社区  ›  Peter Kozlovsky

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

  •  14
  • Peter Kozlovsky  · 技术社区  · 6 年前

    我有这样的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子句实现。打开 条款在JPA 2.1规范中定义,可由 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 回复  |  直到 6 年前
        1
  •  10
  •   HL'REB    6 年前

    你说得对,当你添加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。

        2
  •  5
  •   Victor    3 年前

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

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

    然后出现3例:

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

    在状态从3的情况下,你将失去所有行与活动完全。但获取具有1个状态的

    因为 当postList的列表不为空时,left join不会连接null .

        3
  •  0
  •   Dherik Pascal Sancho    6 年前

    它是 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")