我有以下课程:
@Entity @Table(name = "base") @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.STRING) @ForceDiscriminator public class Base { // ... } @Entity @DiscriminatorValue("foo") public class Foo extends Base { @OneToMany( mappedBy = "foo", cascade=CascadeType.ALL ) private List<Bar> bars = new ArrayList<Bar>(); // ... } @Entity public class Bar { @ManyToOne (optional = false) @JoinColumn(name = "foo_id" ) private Foo foo; @OneToOne @JoinColumn(name = "baz_id", nullable = false) private Baz baz; //... } @Entity public class Baz { // ... }
现在,我基本上想加载all Base,但在适用时渴望加载条,所以我使用以下查询:
Base
SELECT b FROM Base b LEFT JOIN FETCH b.bars
在这种情况下,似乎为Bar实体产生了SELECT N + 1问题:
Hibernate: /* SELECT b FROM Base b LEFT JOIN FETCH b.bars */ SELECT ... Hibernate: /* load com.company.domain.Baz */ SELECT ... Hibernate: /* load com.company.domain.Baz */ SELECT ...
是否可以告诉hibernate急切地为子集合中的每个元素加载一个关联,而无需诉诸N + 1 SELECT?
我尝试了以下查询,但由于它是一个集合,因此显然无法正常工作:
SELECT b FROM Base b LEFT JOIN FETCH b.bars LEFT JOIN FETCH b.bars.baz //Results in: illegal attempt to dereference collection [Foo.id.bars] with element property reference [baz]
我也尝试使用IN(b.bars) bars,虽然这使我可以引用子集合,但似乎并没有急于加载bars集合,这是我的目标。
IN(b.bars) bars
解释为什么会发生这种情况也很好,因为我似乎无法弄清楚。
如果您想不选择(n + 1)来检索Bar and Baz,请使用以下hql。
SELECT b FROM Base b LEFT JOIN FETCH b.bars bar LEFT JOIN FETCH bar.baz
这应该只导致一个sql。
另外,如果您不想获取’Baz’,则只需从Bar-> Baz’lazy’中进行关联即可。
默认情况下,JPA对“ @OneToOne”和“ @ManyToOne”关联强制执行“紧急”获取。因此,您必须显式使其变得懒惰,如下所示。
@Entity public class Bar { @OneToOne @JoinColumn(name = "baz_id", nullable = false, fetch=FetchType.Lazy) private Baz baz; //... }