简体   繁体   English

MappedBy双向@ManyToMany:原因是什么

[英]MappedBy in bi-directional @ManyToMany : what is the reason

  1. What is the reason for setting MappedBy in bidirectional many-to-many relationships? 在双向多对多关系中设置MappedBy的原因是什么?
  2. When one table has significant amount of records, while other has a few, which side is better to put mappedBy? 当一个表有大量的记录,而其他表有几个,哪一方更好地放置mappedBy?

It's actually a good question, and it helps to understand the concept of an "owning" entity. 这实际上是一个很好的问题,它有助于理解“拥有”实体的概念。 If you want to prevent both sides (in a bidirectional relationship) from having join tables , a good idea, then you need to have a mappedBy= element on one side. 如果你想防止双方(双向关系)有join tables ,一个好主意,那么你需要在一侧有一个mappedBy=元素。

Whether or not there is a join table is controlled by the mappedBy="name" element of the @ManyToMany annotation. 是否存在join table@ManyToMany注释的mappedBy="name"元素@ManyToMany The Javadoc for mappedBy for the ManyToMany annotation says : ManyToMany注释的mappedByJavadoc说

The field that owns the relationship. 拥有这种关系的领域。 Required unless the relationship is unidirectional. 除非关系是单向的,否则是必需的。

For your (bidirectional) example, if there were only two @ManyToMany annotations and no mappedBy= element, the default will have two Entity tables and two Join Tables : 对于(双向)示例,如果只有两个@ManyToMany注释而没有mappedBy=元素,则默认将具有两个Entity表和两个Join Tables

Hibernate: create table SideA (id bigint not null, primary key (id))
Hibernate: create table SideA_SideB (sidea_id bigint not null, sidebs_id bigint not null, primary key (sidea_id, sidebs_id))
Hibernate: create table SideB (id bigint not null, primary key (id))
Hibernate: create table SideB_SideA (sideb_id bigint not null, sideas_id bigint not null, primary key (sideb_id, sideas_id))

While this is saying that each Entity "owns" its ManyToMany relationship, the extra join table is redundant in the typical use case, and the Javadoc says you need a mappedBy annotation. 虽然这说明每个实体“拥有”其ManyToMany关系,但额外的join table在典型的用例join table是多余的,而Javadoc说你需要一个mappedBy注释。 If I decide to have SideA "own" the relationship, then I add the mappedBy= element to the SideB entity to specify that it doesn't own the relationship: 如果我决定让SideA“拥有”该关系,那么我将mappedBy=元素添加到SideB实体以指定它不拥有该关系:

@Entity
public class SideA {
    @ManyToMany
    Set<SideB> sidebs;
}
@Entity
public class SideB {
    @ManyToMany(mappedBy="sidebs")
    Set<SideA> sideas;
}

Since the SideB entity no longer owns its ManyToMany relationship, the extra JoinTable will not be created: 由于SideB实体不再拥有其ManyToMany关系,因此不会创建额外的JoinTable

Hibernate: create table SideA (id bigint not null, primary key (id))
Hibernate: create table SideB (id bigint not null, primary key (id))
Hibernate: create table SideA_SideB (sideas_id bigint not null, sidebs_id bigint not null, primary key (sideas_id, sidebs_id))

This is important to the developer because he or she must understand that no relationship is persisted unless it's added to the owning entity, in this case the SideA entity. 这对开发人员来说很重要,因为他或她必须明白,除非将关系添加到拥有实体(在本例中为SideA实体),否则不会保持任何关系。

So, if you have a bidirectional ManyToMany relationship, which means you have ManyToMany on both entities involved, then you should add a mappedBy="name" on one of them as per the Javadoc and to avoid having a redundant join table . 因此,如果您具有bidirectional ManyToMany关系,这意味着您在所涉及的两个实体上都有ManyToMany ,那么您应该根据Javadoc在其中一个上添加mappedBy="name"并避免使用冗余join table

As to which side to make the owning entity, there is no correct answer, it depends on what your system thinks is best. 至于创建拥有实体的哪一方,没有正确的答案,这取决于您的系统认为最好的。 The relationship will only be persisted when entries are put in the owning side so you have to ask yourself whether you more commonly change a SideA's list or SideB's list. 这些关系只会在条目被置于拥有方时保持不变,因此您必须问自己是否更常更改SideA's列表或SideB's列表。 If SideA owns the relationship then you update the relationship by adding or removing SideB instances from a SideA instance but if you had a list of SideA instances for a SideB that you wanted to persist you would need to iterate through the list and alter each instance of SideA in the list. 如果SideA拥有的关系,那么你通过添加或删除更新的关系SideB从实例SideA实例,但如果你有一个清单SideA的情况下SideB ,你要坚持,你就需要通过列表迭代和修改的每个实例SideA在列表中。

As always, it's always a good idea to enable the sql logs and see what's going on in the database: 与往常一样,启用sql日志并查看数据库中发生的情况始终是个好主意:

EDIT: If you have a persistence provider that only creates a single join table with no mappedBy setting then you have to check with the docs to see which side "owns" the relationship. 编辑:如果你有一个只创建一个没有mappedBy设置的连接表的持久性提供程序,那么你必须检查文档以查看哪一方“拥有”该关系。 Could be that neither or both sides own it and that updating neither or either side will persist the entity. 可能是双方都不拥有它,并且任何一方或任何一方都不会更新该实体。

References: 参考文献:

What is the difference between Unidirectional and Bidirectional associations? 单向和双向关联有什么区别? .

What does relationship owner means in bidirectional relationship? 关系所有者在双向关系中意味着什么? .

What is the “owning side” in an ORM mapping? ORM映射中的“拥有方”是什么? .

Most efficient way to prevent an infinite recursion in toString()? 防止toString()中无限递归的最有效方法? .

mappedBy links both sides of a BIDIRECTIONAL relation. mappedBy链接双向关系的两侧。 You put mappedBy on the OWNER of the relation, not based on how many records something has (aka object oriented design). 您将mappedBy放在关系的OWNER上,而不是基于某些记录有多少(也就是面向对象的设计)。 You will find this information in any JPA tutorial and documentation. 您可以在任何JPA教程和文档中找到此信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM