首页 > 解决方案 > Hibernate:如何强制对所有嵌套属性进行单个查询?

问题描述

***感谢@christian-beikov,此问题已更新为完整的模型和更集中的问题

如果我通过 Id 查询 Moose 实体,生成的查询将在单个查询中加入第一个 Mooseling(包括相关的 Gooseling),但第二个 Mooseling.Gooseling 将在第二个 SELECT 语句中查询。

从调试输出中可以清楚地看出,它确定 mooseling2.gooseling 是“被认为是循环的”。有没有办法覆盖它并强制它在一个查询中加载整个树?

我在 Moose 对象上尝试了 @NamedEntityGraph,但这并没有改变任何东西。

2021-02-18 15:20:29.423 DEBUG 7909 --- [           main] o.h.p.entity.AbstractEntityPersister     : Static SQL for entity: com.fetchpackage.domain.entity.Moose
2021-02-18 15:20:29.423 DEBUG 7909 --- [           main] o.h.p.entity.AbstractEntityPersister     :  Version select: select moose_id from mooses where moose_id =?
2021-02-18 15:20:29.423 DEBUG 7909 --- [           main] o.h.p.entity.AbstractEntityPersister     :  Snapshot select: select moose_.moose_id, moose_.mooseling_1_id as mooselin3_37_, moose_.mooseling_2_id as mooselin4_37_, moose_.other_num as other_nu2_37_ from mooses moose_ where moose_.moose_id=?
2021-02-18 15:20:29.423 DEBUG 7909 --- [           main] o.h.p.entity.AbstractEntityPersister     :  Insert 0: insert into mooses (mooseling_1_id, mooseling_2_id, other_num, moose_id) values (?, ?, ?, ?)
2021-02-18 15:20:29.423 DEBUG 7909 --- [           main] o.h.p.entity.AbstractEntityPersister     :  Update 0: update mooses set mooseling_1_id=?, mooseling_2_id=?, other_num=? where moose_id=?
2021-02-18 15:20:29.423 DEBUG 7909 --- [           main] o.h.p.entity.AbstractEntityPersister     :  Delete 0: delete from mooses where moose_id=?
2021-02-18 15:20:29.423 DEBUG 7909 --- [           main] o.h.p.entity.AbstractEntityPersister     :  Identity insert: insert into mooses (mooseling_1_id, mooseling_2_id, other_num) values (?, ?, ?)
2021-02-18 15:20:29.423 DEBUG 7909 --- [           main] o.h.l.p.b.i.spaces.QuerySpacesImpl       : Adding QuerySpace : uid = <gen:0> -> org.hibernate.loader.plan.build.internal.spaces.EntityQuerySpaceImpl@7ec9780b]
2021-02-18 15:20:29.423 DEBUG 7909 --- [           main] o.h.p.walking.spi.MetamodelGraphWalker   : Visiting attribute path : mooseling1
2021-02-18 15:20:29.423 DEBUG 7909 --- [           main] o.h.l.p.b.i.spaces.QuerySpacesImpl       : Adding QuerySpace : uid = <gen:1> -> org.hibernate.loader.plan.build.internal.spaces.EntityQuerySpaceImpl@7101fb1c]
2021-02-18 15:20:29.423 DEBUG 7909 --- [           main] o.h.p.walking.spi.MetamodelGraphWalker   : Visiting attribute path : mooseling1.gooseling
2021-02-18 15:20:29.423 DEBUG 7909 --- [           main] o.h.l.p.b.i.spaces.QuerySpacesImpl       : Adding QuerySpace : uid = <gen:2> -> org.hibernate.loader.plan.build.internal.spaces.EntityQuerySpaceImpl@4c974fe8]
2021-02-18 15:20:29.424 DEBUG 7909 --- [           main] o.h.p.walking.spi.MetamodelGraphWalker   : Visiting attribute path : mooseling1.gooseling.gooseData
2021-02-18 15:20:29.424 DEBUG 7909 --- [           main] o.h.p.walking.spi.MetamodelGraphWalker   : Visiting attribute path : mooseling2
2021-02-18 15:20:29.424 DEBUG 7909 --- [           main] o.h.l.p.b.i.spaces.QuerySpacesImpl       : Adding QuerySpace : uid = <gen:3> -> org.hibernate.loader.plan.build.internal.spaces.EntityQuerySpaceImpl@3c88bef5]
2021-02-18 15:20:29.424 DEBUG 7909 --- [           main] o.h.p.walking.spi.MetamodelGraphWalker   : Visiting attribute path : mooseling2.gooseling
2021-02-18 15:20:29.424 DEBUG 7909 --- [           main] o.h.p.walking.spi.MetamodelGraphWalker   : Property path deemed to be circular : mooseling2.gooseling
2021-02-18 15:20:29.424 DEBUG 7909 --- [           main] o.h.p.walking.spi.MetamodelGraphWalker   : Visiting attribute path : otherNum
2021-02-18 15:20:29.424 DEBUG 7909 --- [           main] lanBuildingAssociationVisitationStrategy : Building LoadPlan...
2021-02-18 15:20:29.424 DEBUG 7909 --- [           main] h.l.p.e.i.LoadQueryJoinAndFetchProcessor : processing queryspace <gen:0>
2021-02-18 15:20:29.425 DEBUG 7909 --- [           main] o.h.l.p.build.spi.LoadPlanTreePrinter    : LoadPlan(entity=com.fetchpackage.domain.entity.Moose)
@NamedEntityGraph(
    name = "moose-mooseling-gooseling-entity-graph",
    attributeNodes = {
        @NamedAttributeNode(value = "mooseling1", subgraph = "mooseling-gooseling-subgraph"),
        @NamedAttributeNode(value = "mooseling2", subgraph = "mooseling-gooseling-subgraph"),
    },
    subgraphs = {
        @NamedSubgraph(
            name = "mooseling-gooseling-subgraph",
            attributeNodes = {
                @NamedAttributeNode("gooseling")
            }
        )
    }
)
@Entity
@Table(name = "mooses")
public class Moose {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer mooseId;

  @Column
  @NotNull
  private Integer otherNum;

  @ManyToOne
  @JoinColumn(name = "mooseling_1_id")
  private Mooseling mooseling1;

  @ManyToOne
  @JoinColumn(name = "mooseling_2_id")
  private Mooseling mooseling2;
}

@Entity
@Table(name = "mooselings")
public class Mooseling {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer mooselingId;

  @ManyToOne
  @JoinColumn(name = "gooseling_id")
  private Gooseling gooseling;
}
@Entity
@Table(name = "gooselings")
public class Gooseling {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer gooselingId;

  @Column
  @NotNull
  private Integer gooseData;
}

标签: hibernate

解决方案


我想这与循环有关,但是由于您没有共享整个模型,因此很难确定。从关系结构中获取对象图的问题在于,它可能具有无法使用 SQL 中的普通连接建模的循环。所以 Hibernate 必须在某个时候停止加入,并使用专用的 select 语句加载其余部分。

首先,不要使用 EAGER fetching。以后会咬你的。始终使用 LAZY 获取关联。然后,您可以在 HQL 查询中使用实体图或 join fetch 来仅连接您实际需要用于用例的关联。


推荐阅读