下面两个声明究竟有什么不同
B是拥有方
@Entity
class A {
@Id int id;
@OneToOne
B b;
}
@Entity
class B {
@Id int id;
@OneToOne(mappedBy="b")
A a;
}
A是拥有方
@Entity
class A {
@Id int id;
@OneToOne(mappedBy="a")
B b;
}
@Entity
class B {
@Id int id;
@OneToOne
A a;
}
在“普通SQL”中考虑这一点,我认为这与两个表中的每个表都有另一个表的外键是一样的。我不明白的是指定哪个实体是拥有方的效果是什么,即使用'mappedBy'属性。这实际上实现了什么,因为我不相信在普通的SQL中有等效的。
5条答案
按热度按时间s2j5cfk01#
JPA 2.0 specification第2.9节写道:
关系可以是双向的,也可以是单向的。双向关系既有拥有方,也有反向(非拥有)方。单向关系只有拥有的一方。关系的拥有方决定数据库中关系的更新,如3.2.4节所述。
以下规则适用于双向关系:
OneToOne
、OneToMany
或ManyToMany
注解的mappedBy
元素来引用其拥有端。mappedBy
元素指定实体中作为关系所有者的属性或字段。ManyToOne
注解中指定mappedBy
元素。第3.2.4节的相关部分为:
持久化实体的状态在事务提交时同步到数据库。这种同步涉及将对持久化实体及其关系的任何更新写入数据库,如上面所指定的。
和
托管实体之间的双向关系将基于关系的拥有方所持有的引用来持久化。开发人员有责任在内存中的引用发生变化时,保持拥有方和反向方的引用保持一致。在单向的一对一和一对多关系的情况下,开发人员有责任确保遵守关系的语义。
bybem2ql2#
拥有方是JPA认为知道关联是否存在的一方。假设你用你的第一个例子。拥有方是没有mappedBy属性的那一方。因此,拥有方是A,而不是B。
这意味着,如果数据库中有一个A和一个B,
JPA将保存关联(即它将把B的ID存储在表A的连接列中)。
但如果你
数据库中没有任何变化,因为你修改了反向端,忘记修改拥有端。
t2a7ltrp3#
正如其他人所指出的,你在例子中关于哪一方是拥有方的问题上是错误的。对于拥有方,我们的意思是从OO的Angular 拥有关系,在实践中,如果使用rdbm作为持久性提供者,那么它通常会与在db中生成或将生成的关系相反。
在正常情况下,OO模型很清楚地表明了哪一方是拥有方。例如,订单具有OrderLines。如果我们删除一个订单,所有的订单行都应该被删除。如果我们删除一个OrderLine,订单可能仍然有存在的权利。因此,命令是拥有方。
对于一个更具体和优秀的例子,关于哪一方是拥有方的影响,我参考了@JB Nizet的答案。
根据JPA 2.0 spec的第2.9节:
对于一对一双向关系,拥有方对应于包含相应外键的一方。
但在同一节中,我们也有:
此外,本规范还要求支持以下备选Map策略:[..]通过连接表Map实现单向和双向一对一关系、双向多对一/一对多关系以及单向多对一关系的Map。
在同一节中再往下一点,它继续说:
可以指定附加的Map注解(例如,列和表Map注解)来覆盖或进一步细化第2.10节中描述的默认Map和Map策略。一些实现利用这一点来允许一对一双函数的FK位于目标表中。
要阅读一些解决这种情况的策略,请参阅:一个几乎很好的解释
我还没有检查,但我希望并相信2.1将删除第一个报价。因为实际的数据库结构应该尽可能少地限制我们如何将数据建模为实体。
v1uwarro4#
在第一个例子中,
A
表将有两列id
和b_id
,B
表将有一列id
。这使得A
成为拥有方。在第二个例子中,
B
是拥有方。B
有两列,id
和a_id
。A
只有一列id
。这就是区别:-)
wgeznvg75#
您提供的示例是***一对一双向***关系。
双向关系意味着 * 两个实体将在域模型中存储彼此的引用 *。但是,
在双向关系中,有:
让我们参考你的第一个例子来理解这一点。
(我添加了
@JoinColumn
和Table
注解,使初学者更清楚)。这里,假设实体
A
和B
的对应表分别是a
和b
。我们在实体
A
中使用了@JoinColumn
,并将其值设置为b_id
。这意味着将在表a
中创建一个名为b_id
的列,该列将存储id
或表b
的引用。此列b_id
也用作外键。注意,虽然是双向关系,因为,表
a
存储关系信息,即对于表b
的引用,其对应的实体A
被称为 * 所有者实体 *。另一个实体
B
称为引用实体。它使用mappedBy
属性引用所有者实体A
。类似地,在第二个示例中,
B
是拥有实体,A
是 * 引用实体 *。