Hibernate/JPA 多对一与单对多
Posted
技术标签:
【中文标题】Hibernate/JPA 多对一与单对多【英文标题】:Hibernate/JPA ManyToOne vs OneToMany 【发布时间】:2013-04-13 17:26:56 【问题描述】:我目前正在阅读有关 entity associations 的 Hibernate 文档,但我在弄清楚一些事情时遇到了一些困难。它本质上与ManyToOne
和OneToMany
关联之间的区别有关。尽管我在实际项目中使用过它们,但我无法完全理解它们之间的区别。据我了解,如果一个表/一个实体与另一个有ManyToOne
关联,那么该关联应该来自另一方OneToMany
。那么,我们应该如何根据具体情况决定选择哪一个,以及它如何影响数据库/查询/结果?到处都有很好的例子吗?
P.S.:由于它与问题的相关性,我认为它会有所帮助,如果有人可以解释关联所有者的意义以及双向和单向关联之间的区别。
【问题讨论】:
【参考方案1】:假设您有一个 Order 和一个 OrderLine。您可以选择在 Order 和 OrderLine 之间使用单向 OneToMany(Order 将具有 OrderLines 的集合)。或者,您可以选择在 OrderLine 和 Order 之间建立 ManyToOne 关联(OrderLine 将引用其 Order)。或者您可以选择两者都有,在这种情况下,关联变为双向 OneToMany/ManyToOne 关联。
您选择的解决方案主要取决于情况,以及实体之间的耦合程度。例如,如果用户、公司、提供商都有很多地址,那么在每个人与 Address 之间建立单向地址是有意义的,并且 Address 不知道他们的所有者。
假设您有一个用户和一个消息,其中一个用户可以有数千条消息,将其仅建模为从消息到用户的多对一可能是有意义的,因为您很少会询问用户的所有消息反正。不过,可以将关联设置为双向,以帮助查询,因为 JPQL 查询通过浏览实体之间的关联来连接实体。
在双向关联中,您可能会遇到对象图不一致的情况。例如,Order A 将有一组空的 OrderLines,但某些 OrderLines 会引用 Order A。JPA 强制要求始终将关联的一侧作为所有者,而将另一侧作为反向。 JPA 忽略反面。所有者方是决定存在什么关系的一方。在 OneToMany 双向关联中,所有者方必须是多方。因此,在前面的示例中,所有者方是 OrderLine,而 JPA 将保持行与订单 A 之间的关联,因为行具有对 A 的引用。
这样的关联会被映射成这样:
按顺序:
@OneToMany(mappedBy = "parentOrder") // mappedBy indicates that this side is the
// inverse side, and that the mapping is defined by the attribute parentOrder
// at the other side of the association.
private Set<OrderLine> lines;
在订单行中:
@ManyToOne
private Order parentOrder;
【讨论】:
【参考方案2】:此外,将@ManytoOne
作为所有者,在保存关联时只需要 n+1 个查询。其中 n 是关联的数量(多边)。
虽然拥有 @OneToMany
作为所有者,但在插入父实体(一侧)和关联(多侧)时会导致 2*N + 1 次查询。其中一个查询用于插入关联,另一个查询用于更新关联实体中的外键。
【讨论】:
【参考方案3】:虽然以上答案是准确的,但我会以不同的方式呈现答案。
@OneToMany
和 @ManyToOne
都有两个部分;左侧部分和右侧部分。例如:
@OneToMany
= 'One' 是左侧部分,'Many' 是右侧部分
@ManyToOne
= 'Many' 是左侧部分,'One' 是右侧部分
使用这种理解的简单关联规则是,左侧部分代表您正在定义关联的类。
因此,如果您在 OrderLine 类中定义 @ManyToOne
引用 Order 类,则意味着多个 OrderLine 关联到一个 Order 类。
【讨论】:
【参考方案4】:我将通过一个例子来回答。假设您有一个 Ordering 或 POS 系统的设计。然后,每个订单都有订单详细信息(例如产品)。在这种情况下,我们有一个@oneToMany
关系。这同样适用于销售和销售细节关系。
如果我有一个用户表并且每个用户都绑定到一个特定的商店,那么我们可以让许多用户绑定到同一个商店,因此 @manyToOne
。
【讨论】:
以上是关于Hibernate/JPA 多对一与单对多的主要内容,如果未能解决你的问题,请参考以下文章