java JPA - 使用mappedBy 属性来定义拥有实体的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10968536/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 03:15:30  来源:igfitidea点击:

JPA - difference in the use of the mappedBy property to define the owning entity

javahibernatejpapersistencejpql

提问by ziggy

What exactly is the difference in the following two declarations

下面两个声明到底有什么区别

B is the owning side

B是拥有方

@Entity
class A {
   @Id int id;

   @OneToOne
   B b;
}

@Entity
class B {
   @Id int id;

   @OneToOne(mappedBy="b")
   A a;
}

A is the owning side

A是拥有方

@Entity
class A {
   @Id int id;

   @OneToOne(mappedBy="a")
   B b;
}

@Entity
class B {
   @Id int id;

   @OneToOne
   A a;
}

Thinking of this in "normal SQL" i think it is the same as having two tables each having the other table's foreign key. What i don't understand though is what is the effect of specifying which entity is the owning side i.e using the 'mappedBy' property. What does this actually achieve as i don't believe there is an equivalent in normal SQL.

在“普通 SQL”中考虑到这一点,我认为这与有两个表相同,每个表都有另一个表的外键。我不明白的是,指定哪个实体是拥有方的效果是什么,即使用“mappedBy”属性。这实际上实现了什么,因为我不相信在普通 SQL 中存在等价物。

回答by meriton

The JPA 2.0 specification, section 2.9, writes:

JPA 2.0规范,第2.9节,写:

Relationships may be bidirectional or unidirectional. A bidirectional relationship has both an owning side and an inverse (non-owning) side. A unidirectional relationship has only an owning side. The owning side of a relationship determines the updates to the relationship in the database, as described in section 3.2.4.

The following rules apply to bidirectional relationships:

  • The inverse side of a bidirectional relationship must refer to its owning side by use of the mappedByelement of the OneToOne, OneToMany, or ManyToManyannotation. The mappedByelement designates the property or field in the entity that is the owner of the relationship.
  • The many side of one-to-many / many-to-one bidirectional relationships must be the owning side, hence the mappedByelement cannot be specified on the ManyToOneannotation.
  • For one-to-one bidirectional relationships, the owning side corresponds to the side that contains the corresponding foreign key.
  • For many-to-many bidirectional relationships either side may be the owning side.

关系可以是双向的或单向的。双向关系既有拥有方,也有反向(非拥有)方。单向关系只有一个拥有方。关系的拥有方决定了数据库中关系的更新,如第 3.2.4 节所述。

以下规则适用于双向关系:

  • 的双向关系中的反向端必须通过使用的是指其持有端mappedBy的的元素 OneToOneOneToManyManyToMany注释。该mappedBy元素指定作为关系所有者的实体中的属性或字段。
  • 一对多/多对一双向关系的多方必须是拥有方,因此mappedBy不能在ManyToOne注释上指定元素。
  • 对于一对一的双向关系,拥有方对应于包含相应外键的一方。
  • 对于多对多双向关系,任何一方都可能是拥有方。

The relevant parts of section 3.2.4 are:

第 3.2.4 节的相关部分是:

The state of persistent entities is synchronized to the database at transaction commit. This synchronization involving writing to the database any updates to persistent entities and their relationships as specified above.

持久实体的状态在事务提交时同步到数据库。这种同步涉及向数据库写入对持久实体及其关系的任何更新,如上所述。

and

Bidirectional relationships between managed entities will be persisted based on references held by the owning side of the relationship. It is the developer's responsibility to keep the in-memory references held on the owning side and those held on the inverse side consistent with each other when they change. In the case of unidirectional one-to-one and one-to-many relationships, it is the developer's responsibility to insure that the semantics of the relationships are adhered to.

It is particularly important to ensure that changes to the inverse side of a relationship result in appropriate updates on the owning side, so as to ensure the changes are not lost when they are synchronized to the database.

受管实体之间的双向关系将基于关系拥有方持有的引用而持久化。开发人员有责任在更改时保持拥有方持有的内存引用和反向方持有的内存引用彼此一致。在单向一对一和一对多关系的情况下,开发人员有责任确保遵守关系的语义。

尤其重要的是要确保关系逆向的更改会导致拥有方的相应更新,以确保更改在同步到数据库时不会丢失。

回答by esej

As other have pointed out, you are wrong about which side is the owning side in your examples. With owning side we mean owning the relationship from an OO perspecitve, in practise that quite often ends up being the opposite of how it is or will be generated in the db if one uses a rdbm as persistence provider.

正如其他人所指出的那样,您对示例中哪一方是拥有方的看法是错误的。拥有方是指从 OO 的角度拥有关系,实际上,如果使用 rdbm 作为持久性提供者,这通常最终与它在数据库中的生成方式或将要生成的方式相反。

In normal circumstances the OO model makes it quite clear which sides is the owning side. For example an Order has OrderLines. If we delete an Order all Orderlines should be deleted. If we delete an OrderLine the Order possibly still has a right to existence. Hence, the Order is the owning side.

在正常情况下,OO 模型非常清楚哪一方是拥有方。例如,订单有订单行。如果我们删除一个订单,所有的订单行都应该被删除。如果我们删除一个 OrderLine,这个 Order 可能仍然有存在的权利。因此,订单是拥有方。

For a more concrete and excellent example, on the effects of which side is the owning side, I refer to @JB Nizet answer.

对于更具体和优秀的例子,关于哪一方是拥有方的影响,我参考@JB Nizet 的回答。

According to section 2.9 of the JPA 2.0 spec:

根据JPA 2.0 规范的第 2.9 节:

For one-to-one bidirectional relationships, the owning side corresponds to the side that contains the corresponding foreign key.

对于一对一的双向关系,拥有方对应于包含相应外键的一方。

But in the same section we also have:

但在同一部分,我们也有:

In addition, this specification also requires support for the following alternative mapping strategies: [..] The mapping of unidirectional and bidirectional one-to-one relationships, bidirectional many-to-one/one-to-many relationships, and unidirectional many-to-one relationships by means of join table mappings.

此外,该规范还要求支持以下替代映射策略:[..] 单向和双向一对一关系、双向多对一/一对多关系和单向多对多关系的映射通过连接表映射建立一对一关系。

A bit futher down in the same section it continues with:

在它继续的同一部分中再往下一点:

Additional mapping annotations (e.g., column and table mapping annotations) may be speci- fied to override or further refine the default mappings and mapping strategies described in Section 2.10. Some implementations make use of that to allow the FK of a birectional OneToOne to be in the target table.

可以指定额外的映射注释(例如,列和表映射注释)来覆盖或进一步细化第 2.10 节中描述的默认映射和映射策略。一些实现利用它来允许双向 OneToOne 的 FK 位于目标表中。

To read some about some strategies to solve that scenario, see: An almost good explaination

要阅读有关解决该场景的一些策略的一些信息,请参阅:几乎很好的解释

I haven't checked but I do hope and believe that 2.1 will remove the first quote. Since the actual database structure should put as little limit as possible on how we can model data as entities.

我还没有检查过,但我确实希望并相信 2.1 会删除第一个引用。由于实际的数据库结构应该尽可能少地限制我们如何将数据建模为实体。

回答by siebz0r

In the first example the Atable is going to have 2 columns idand b_id, the Btable is going to have one column, id. This makes Athe owning side.

在第一个示例中,该A表将有 2 列,id并且b_idB表将有一个列,id。这使得A拥有方。

In the second example Bis the owning side. Bhas two columns, idand a_id. Ais going to have one column, id.

第二个例子B是拥有方。B有两列,ida_idA将有一列,id.

And that is the difference :-)

这就是区别:-)

回答by JB Nizet

The owning side is the side that JPA considers to know is the association exists or not. Suppose you go with your first example. The owning side is the side where there is no mappedBy attribute. The owning side is thus A, and not B.

拥有方是 JPA 认为知道关联是否存在的一方。假设您使用第一个示例。拥有方是没有mappedBy 属性的一方。因此,拥有方是 A,而不是 B。

This means that if you have an A and a B in database, and you do

这意味着,如果您在数据库中有一个 A 和一个 B,并且您这样做

A a = em.find(A.class, aId);
B b = em.find(B.class, bId);
a.setB(b);

JPA will save the association (i.e. it will store the ID of B in the join column of table A).

JPA 将保存关联(即它会将 B 的 ID 存储在表 A 的连接列中)。

But if you do

但是如果你这样做

A a = em.find(A.class, aId);
B b = em.find(B.class, bId);
b.setA(a);

nothing will be changed in database, because you modified the inverse side and forgot to modify the owning side.

数据库中的任何内容都不会更改,因为您修改了反面而忘记修改拥有面。