65

我目前正在阅读有关实体关联的 Hibernate 文档,我遇到了一些困难来弄清楚一些事情。ManyToOne它本质上与关联之间的差异OneToMany有关。尽管我在实际项目中使用过它们,但我无法完全理解它们之间的区别。据我了解,如果一个表/一个实体ManyToOne与另一个有关联,那么该关联应该来自另一方OneToMany。那么,我们应该如何根据具体情况决定选择哪一个,以及它如何影响数据库/查询/结果?到处都有很好的例子吗?

PS:由于它与问题的相关性,我认为它会有所帮助,如果有人可以解释关联所有者的意义以及双向和单向关联之间的区别。

4

4 回答 4

80

假设您有一个 Order 和一个 OrderLine。您可以选择在 Order 和 OrderLine 之间使用单向 OneToMany(Order 将具有 OrderLines 的集合)。或者,您可以选择在 OrderLine 和 Order 之间建立 ManyToOne 关联(OrderLine 将引用其 Order)。或者您可以选择两者都有,在这种情况下,关联变为双向 OneToMany/ManyToOne 关联。

您选择的解决方案主要取决于情况,以及实体之间的耦合程度。例如,如果用户、公司、提供商都有很多地址,那么在每个人与 Address 之间有一个单向的地址是有意义的,并且 Address 不知道他们的所有者。

假设您有一个 User 和一个 Message,其中一个用户可以有数千条消息,将其建模为从 Message 到 User 的 ManyToOne 是有意义的,因为无论如何您很少会询问用户的所有消息。不过,关联可以是双向的,只是为了帮助查询,因为 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;
于 2013-04-20T11:19:16.387 回答
10

此外,@ManytoOne在保存关联时,将一方作为所有者只需要 n+1 个查询。其中 n 是关联的数量(多边)。

@OneToMany作为所有者,在插入父实体(一侧)与关联(多侧)时会导致 2*N + 1 个查询。其中一个查询将用于插入关联,而另一个查询将用于更新关联实体中的外键。

于 2017-03-25T07:47:17.943 回答
7

虽然以上答案是准确的,但我将以不同的方式呈现答案。

两者@OneToMany都有@ManyToOne两个部分;左侧部分和右侧部分。例如:

  • @OneToMany= 'One' 是左侧部分,'Many' 是右侧部分
  • @ManyToOne= 'Many' 是左侧部分,'One' 是右侧部分

使用这种理解的简单关联规则是,左侧部分代表您正在定义关联的类。

因此,如果您@ManyToOne在 OrderLine 类中定义引用 Order 类,则意味着多个 OrderLine 关联到一个 Order 类。

于 2020-11-18T14:42:59.930 回答
0

我将通过一个例子来回答。假设您有一个 Ordering 或 POS 系统的设计。然后,每个订单都有订单详情(例如产品)。在这种情况下,我们有@oneToMany关系。这同样适用于销售和销售细节关系。

如果我有一个用户表并且每个用户都绑定到一个特定的商店,那么我们可以让许多用户绑定到同一个商店@manyToOne

于 2020-11-18T08:24:55.477 回答