从数据库加载实体时,我使用@NamedEntityGraph. 我试图在这样的查询中使用这样的图表:
@EntityGraph(value = "paragraph-graph-questions")
@Query("SELECT sp FROM Paragraph p JOIN p.subParagraphs sp WHERE p.id=:id")
Set<Paragraph> getAllSubParagraphs(int id);
这会导致以下错误:
org.hibernate.QueryException: query specified join fetching,
but the owner of the fetched association was not present in the select list ...
需要注意的是,这种情况下的请求是自反的,因为实体通过 OneToMany 关系Paragraph引用其他实体:Paragraph
@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;
}
我决定你不能同时使用JOIN两者EntityGraph,因为这会导致错误。但是,显然,一切都不是那么明确,因为这样的查询可以与实体图一起正常工作:
@EntityGraph(value = "report-graph-low")
@Query("""
SELECT r FROM Report r
LEFT JOIN r.themeDetails td ON td.theme.id=:themeId
LEFT JOIN r.paragraphDetails pd ON pd.paragraph.theme.id=:themeId
LEFT JOIN r.offlineThemeDetails od ON od.theme.id=:themeId
WHERE r.student.id=:studentId
""")
List<Report> getAllByStudentIdAndThemeId(int studentId, int themeId, Pageable pagination);
在实体的情况下,Report没有自反关系。
为什么它在一种情况下失败而在另一种情况下失败?如何subParagraphs使用实体图获取集合?
PS:我知道我可以在 Paragraph 字段 Paragraph parent 中做什么,确实会更容易,但我想以不同的方式来做。
显然,错误的原因根本不是在使用,而是因为在尝试加载所有者的图形时,
JOIN样本中没有获取关系的所有者,而是与其关联的实体@EntityGraph的关系。在方法
getAllSubParagraphs中,我尝试了不同的请求变体,但它们都给出了错误:我决定从另一边出发并尝试提出这样的请求,其中它将是将被选中的关联的所有者,而不是其子实体:
它真的奏效了。
Hibernate生成以下请求:结果,正是这样一个图表被加载,这是我想要的。
可能这样的查询不是最优的。这是一个额外的
SELECT。最好在 entity 中创建一个Paragraph字段Paragraph parent,然后请求会更简单:因此,如果您要加载带有图表的实体,请卸载关联的所有者,因为图表将从他那里加载。