【发布时间】:2011-08-11 12:09:07
【问题描述】:
Hibernate 3.3 存在 n+1 选择问题。
为简单起见,我只做一个简短的抽象示例。
假设我们有以下简单的类:
class MainEntity {
@Id
public Long id; //we have a table generator create this id
@OneToOne ( mappedBy ="main" )
public SubEntity subEntity;
}
class SubEntity {
@Id
@Column( name = "mainId" ) //note that this is the same column as the join column below
public Long mainId; //in order to have the exact same id as the corresponding MainEntity
@OneToOne ( fetch = FetchType.LAZY )
@JoinColumn ( name = "mainId", insertable = false, updatable = false, nullable = false )
public MainEntity main; //this is used for navigation and queries (" ... subentity.main = :x")
}
如您所见,SubEntity 与MainEntity 有一个关系,由两个属性表示,其中mainId 属性负责管理关系/外键。
这很好用,完全符合我们的需求。
但是,急切地加载SubEntity 和MainEntity 存在一个问题。
假设我有一个返回MainEntity 集合的查询。在当前设置下,Hibernate 将发出 n + 1 个选择:查询本身 + n 对每个 SubEntity 选择。
当然,我可以在查询中添加join fetch,但我更希望 Hibernate 自动执行此操作。因此我尝试添加@Fetch( FetchMode.JOIN ),但没有任何作用。
使用@Fetch( FetchMode.SUBSELECT ) 也没有问题,这应该将选择语句减少到 2 - 原始查询和子实体的选择(至少这是在另一个用 @CollectionOfElements 和 @987654333 注释的属性上发生的情况@)。
所以问题是:我将如何告诉 Hibernate 自动加入 fetch 或使用单个选择来急切地加载子实体?我错过了什么吗?
提前致谢,
托马斯
PS:可能有问题的一件事是 mappedBy = "main" 没有引用实际的 id 列,但我无法将其更改为 mappedBy = "id"。
【问题讨论】: