【问题标题】:Why using @NamedEntityGraph throw exception?为什么使用@NamedEntityGraph 抛出异常?
【发布时间】:2021-08-19 20:55:15
【问题描述】:

我有Spring Boot 应用程序。在应用中存在实体:

@NamedEntityGraph(
        name = "paragraph-graph-questions",
        attributeNodes = {
                @NamedAttributeNode(value = "questions")
        })
@Entity
@Table(name = "paragraphs")
public class Paragraph {

    @Id
    private Integer id;

    @OneToMany(mappedBy = "paragraph")
    private Set<Question> questions;

    @OneToMany
    @JoinTable(
            name = "sub_paragraphs",
            joinColumns = @JoinColumn(name = "paragraph_id"),
            inverseJoinColumns = @JoinColumn(name = "sub_paragraph_id")
    )
    private Set<Paragraph> subParagraphs;
}

特点是Paragraph实体与其他段落具有反身OneToMany关系。我制作了 JpaRepository 以便获得段落的子段落:

@Transactional(readOnly = true)
public interface ParagraphDao extends JpaRepository<Paragraph, Integer> {

    @EntityGraph(value = "paragraph-graph-questions")
    @Query("SELECT sp FROM Paragraph p JOIN p.subParagraphs sp WHERE p.id=:id")
    Set<Paragraph> getAllSubParagraphs(int id);
}

但是如果我在这个方法中使用@EntityGraph,调用这个方法会抛出异常,否则方法工作正常。这是我在使用@EntityGraph 时得到的异常堆栈跟踪:

org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list [FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=sp,role=ru.zhenyria.deeptest.model.task.Paragraph.subParagraphs,tableName=paragraphs,tableAlias=paragraph2_,origin=paragraphs paragraph0_,columns={paragraph0_.id,className=ru.zhenyria.deeptest.model.task.Paragraph}}]

我该如何解决?谢谢。

【问题讨论】:

    标签: java spring-boot spring-data-jpa jpql entitygraph


    【解决方案1】:

    似乎不支持以这种方式使用@EntityGraph

    假设您想要获取段落的所有直接SubParagraphs,包括他们在单个选择语句中的所有问题,您可以使用如下实体图:

    @NamedEntityGraph(name = "subParagraphsWithQuestions", attributeNodes = {
      @NamedAttributeNode(value = "subParagraphs", subgraph = "subgraph") }, subgraphs = {
        @NamedSubgraph(name = "subgraph", attributeNodes = { @NamedAttributeNode(value = "questions") }) })
    

    它可以与这样的存储库查询一起使用:

    @EntityGraph(value = "subParagraphsWithQuestions")
    @Query("SELECT p FROM Paragraph p WHERE p.id=:id")
    Paragraph customFindWithSubParagraphQuestions(@Param("id") long id);
    

    运行此查询时,会直接获取所有与问题相关的子段落,因此访问这些问题不会导致进一步的选择。 (详情请参阅this sample integration-test。)

    这有帮助吗?


    另一种选择是添加逆映射,以便能够通过“parentParagraphId”查询Paragraphs - 这样您就可以在这样的spring-data查询中重用当前的@EntityGraph

    @EntityGraph(value = "paragraph-graph-questions")
    Set<Paragraph> findByParentParagraphId(int id);
    

    【讨论】:

      猜你喜欢
      • 2010-12-09
      • 2011-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-28
      • 2011-12-12
      • 1970-01-01
      • 2013-09-04
      相关资源
      最近更新 更多