我有以下实体:
//The class Entity is a @MappedSuperclass with id, audit fields, equals and so on.
@Entity
public class Foo extends Entity {
@OneToMany(mappedBy = "foo", cascade=CascadeType.ALL, fetch = FetchType.LAZY)
private Set<Bar> bars = new HashSet<Bar>; // + getter/setter
// ... other properties
}
@Entity
public class Bar extends Entity {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "foo_id")
private Foo foo; // +getter/setter
@OneToOne(cascade=CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "baz_id", nullable = false)
private Baz baz; // + getter/setter
// ... other properties
}
@Entity
public class Baz extends Entity {
@OneToOne(mappedBy = "baz", fetch = FetchType.LAZY, optional = false)
private Bar bar; // + getter/setter
// ... other properties
}
现在,如果我用以下内容加载 a Bar
,一切都很好(即只有一个查询发送到数据库):
SELECT bar FROM Bar bar LEFT JOIN FETCH bar.baz WHERE bar.id = :barId
但是,如果我执行以下任一操作,SELECT
则会为每个创建一个新对象Baz
以获取关联Bar
对象:
SELECT f FROM Foo f LEFT JOIN FETCH f.bars bar LEFT JOIN FETCH bar.baz WHERE f.id = :fooId
SELECT f FROM Foo f LEFT JOIN FETCH f.bars bar LEFT JOIN FETCH bar.baz baz LEFT JOIN FETCH baz.bar WHERE f.id = :fooId
输出是:
10:52:08,622 INFO [STDOUT] Hibernate: select ... from Foo ...
10:52:08,698 INFO [STDOUT] Hibernate: select ... from Bar where baz_id=?
10:52:08,711 INFO [STDOUT] Hibernate: select ... from Bar where baz_id=?
... and so on
现在,我从这个答案中了解到@OneToOne
延迟加载存在问题,所以我听从了他们的建议并添加了 optional = false (这对我来说似乎没有多大作用)。
我也尝试了this blogpost中的建议3 ,但这似乎根本没有效果..
任何建议如何急切地获取对象图以避免 SELECT n+1 问题?
我在 JBoss 4.2 服务器上使用 EJB 3 (JPA 1) 和 Hibernate 3.2.4.sp1。
注意:这有点类似于我之前的问题之一。不同之处在于这里Baz
有一个参考,Bar
这似乎是问题所在。