【发布时间】:2012-11-02 22:32:33
【问题描述】:
我有以下课程:
@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 {
// ...
}
现在我基本上想加载所有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 SELECTs?
我尝试了以下查询的内容,但由于它是一个集合,因此显然不起作用:
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,虽然这允许我引用子集合,但它似乎并没有急切地加载 bar 集合,这是我的目标。
解释为什么会发生这种情况也很好,因为我似乎无法弄清楚。
【问题讨论】:
-
您是否遇到 Baz 或 Bar 的“n+1 选择”问题?在您提供的堆栈跟踪跟踪中,看起来 n+1 选择是针对“Baz”的。
-
没错。正如预期的那样,Bar 实体的集合已正确加载,但这种加载显然会强制选择 N 个 Baz 元素。