[英]Hibernate OneToOne automatic join fetching (resolving n+1 problem)
we have a n+1 select problem with Hibernate 3.3. Hibernate 3.3 有一个 n+1 select 问题。
For simplicity's sake, I'll just do a short abstract example.为简单起见,我将只做一个简短的抽象示例。
Suppose we have the following simple classes:假设我们有以下简单的类:
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")
}
So as you can see SubEntity
has a relation to MainEntity
that is expressed by two properties, where the mainId
property is the one responsible for managing the relation/foreign key.如您所见, SubEntity
与MainEntity
的关系由两个属性表示,其中mainId
属性是负责管理关系/外键的属性。
This works quite well and perfectly fits our needs.这工作得很好,完全符合我们的需求。
However, there's one problem with eagerly loading the SubEntity
along with the MainEntity
.但是,急切地加载SubEntity
和MainEntity
存在一个问题。
Suppose I have a query that returns a collection of MainEntity
.假设我有一个返回MainEntity
集合的查询。 With the current setup, Hibernate will issue n + 1 selects: the query itself + n selects for each SubEntity
.使用当前设置, Hibernate 将发出 n + 1 个选择:查询本身 + n 为每个SubEntity
选择。
Of course I could add a join fetch
to the query, but I'd rather like Hibernate to do that automatically.当然,我可以在查询中添加join fetch
,但我更希望 Hibernate 自动执行此操作。 Thus I tried adding @Fetch( FetchMode.JOIN )
, but that didn't do anything.因此我尝试添加@Fetch( FetchMode.JOIN )
,但这并没有做任何事情。
I would also have no problem using @Fetch( FetchMode.SUBSELECT )
, which should reduce the select statements to 2 - the original query and a select for the sub entities (at least that's what happens on another property annotated with @CollectionOfElements
and @Fetch( FetchMode.SUBSELECT )
).使用@Fetch( FetchMode.SUBSELECT )
也没有问题,这应该将 select 语句减少到 2 - 原始查询和子实体的 select (至少这是在另一个用@CollectionOfElements
和@Fetch( FetchMode.SUBSELECT )
注释的属性上发生的情况@Fetch( FetchMode.SUBSELECT )
)。
So the question is: how would I tell Hibernate to automatically join fetch or use a single select in order to eagerly load the sub entities?所以问题是:我如何告诉 Hibernate自动加入 fetch 或使用单个 select 以便急切地加载子实体? Am I missing something?我错过了什么吗?
Thanks in advance,提前致谢,
Thomas托马斯
PS: One thing that might be a problem might be the mappedBy = "main"
which doesn't reference the actual id column, but I can't change it to mappedBy = "id"
. PS:可能有问题的一件事可能是mappedBy = "main"
没有引用实际的 id 列,但我无法将其更改为mappedBy = "id"
。
If you want to shared primary keys between MainEntity and SubEntity use PrimaryKeyJoinColumn
and MapsId
annotation.如果要在 MainEntity 和 SubEntity 之间共享主键,请使用PrimaryKeyJoinColumn
和MapsId
注释。
By using PrimaryKeyJoinColumn
the entity is loaded by joining the MainEntity
table with the SubEntity
table using the same primary key.通过使用PrimaryKeyJoinColumn
,通过使用相同的主键将MainEntity
表与SubEntity
表连接来加载实体。 It should resolve the n+1 problems.它应该可以解决 n+1 个问题。
The MapsId
annotation ask Hibernate to copy the identifier from another associated entity in our example will copy the SubEntity.mainEntity.id
to SubEntity.id
. MapsId
注释要求 Hibernate 从另一个关联实体复制标识符,在我们的示例中,会将SubEntity.mainEntity.id
复制到SubEntity.id
。
@Entity
public class MainEntity {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "main_Id")
private Long id;
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
private SubEntity subEntity ;
}
@Entity
public class SubEntity
{
@Id @Column(name="main_Id_FK") Long id;
@MapsId
@OneToOne
@JoinColumn(name = "main_Id_FK")
@PrimaryKeyJoinColumn
private MainEntity mainEntity;
}
Hibernate Reference Documentation: Hibernate 参考文档:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.