简体   繁体   English

JPA - 使用mappedBy属性来定义拥有实体的不同之处

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

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. 在“普通SQL”中考虑这一点,我认为它与两个表各有另一个表的外键相同。 What i don't understand though is what is the effect of specifying which entity is the owning side ie using the 'mappedBy' property. 我不明白的是,指定哪个实体是拥有方的效果是什么,即使用'mappedBy'属性。 What does this actually achieve as i don't believe there is an equivalent in normal SQL. 这实际上实现了什么,因为我不相信在普通的SQL中有相同的东西。

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. 关系的拥有方确定数据库中关系的更新,如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 mappedBy element of the OneToOne , OneToMany , or ManyToMany annotation. 双向关系的反面必须通过使用OneToOneOneToManyManyToMany批注的mappedBy元素来引用其拥有方。 The mappedBy element designates the property or field in the entity that is the owner of the relationship. mappedBy元素指定作为关系所有者的实体中的属性或字段。
  • The many side of one-to-many / many-to-one bidirectional relationships must be the owning side, hence the mappedBy element cannot be specified on the ManyToOne annotation. 一对多/多对一双向关系的许多方面必须是拥有方,因此不能在ManyToOne批注上指定mappedBy元素。
  • 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. 对于多对多双向关系,任何一方都可能是拥有方。

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. 特别重要的是要确保对关系的反面的更改导致在所有方面进行适当的更新,以确保在它们与数据库同步时不会丢失更改。

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. 在正常情况下,OO模型清楚地表明哪一方是拥有方。 For example an Order has OrderLines. 例如,Order有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. 如果我们删除OrderLine,订单可能仍然有权存在。 Hence, the Order is the owning side. 因此,订单是拥有方。

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 (eg, 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. 可以指定附加的映射注释(例如,列和表映射注释)来覆盖或进一步细化第2.10节中描述的默认映射和映射策略。 Some implementations make use of that to allow the FK of a birectional OneToOne to be in the target table. 一些实现利用它来允许双向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. 我没有检查,但我希望并相信2.1将删除第一个引用。 Since the actual database structure should put as little limit as possible on how we can model data as entities. 由于实际的数据库结构应该尽可能地限制我们如何将数据建模为实体。

In the first example the A table is going to have 2 columns id and b_id , the B table is going to have one column, id . 在第一个例子中, A表将有2列idb_idB表将有一列id This makes A the owning side. 这使A成为拥有者。

In the second example B is the owning side. 在第二个例子中, B是拥有方。 B has two columns, id and a_id . B有两列, ida_id A is going to have one column, id . A将有一列, id

And that is the difference :-) 这就是区别:-)

The owning side is the side that JPA considers to know is the association exists or not. 拥有方是JPA认为知道的关联是否存在。 Suppose you go with your first example. 假设你选择了第一个例子。 The owning side is the side where there is no mappedBy attribute. 拥有方是没有mappedBy属性的一方。 The owning side is thus A, and not B. 拥有方因此是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 (ie 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. 数据库中没有任何内容会被更改,因为您修改了反面并忘记修改拥有方。

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

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