ChatGPT解决这个技术问题 Extra ChatGPT

Hibernate/JPA 多对一与单对多

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

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


J
Jim Kiley

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

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

假设您有一个 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;

m
marc_s

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

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


a
axiopisty

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

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

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

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

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

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


B
Byted

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

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