一尘不染

为什么建议避免在外键上进行单向一对多关联?

hibernate

在Hibernate联机文档中,在7.2.3节“一对多”下提到:

外键上的单向一对多关联是一种不常见的情况,因此不建议这样做。您应该使用联接表进行这种关联。

我想知道为什么?我唯一想到的是,它可能会在级联删除期间产生问题。例如,“人”是指外键上一对多关系上的地址,并且该地址将拒绝在该人之前被删除。

任何人都可以解释该建议背后的合理性吗?

这是参考文档内容的链接:7.2.3。一对多

我已将实际内容复制粘贴到此处:

外键上的单向一对多关联是一种不常见的情况,因此不建议这样做。

<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <set name="addresses">
        <key column="personId"
            not-null="true"/>
        <one-to-many class="Address"/>
    </set>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
</class>

create table Person (personId bigint not null primary key)
create table Address (addressId bigint not null primary key, personId

bigint not null)

您应该使用联接表进行这种关联。


阅读 327

收藏
2020-06-20

共1个答案

一尘不染

外键上的单向一对多关联是一种不常见的情况,因此不建议这样做。

这有两个方面:

  • 单向
  • 一对多

线程
@CalmStorm 的答案被删除的链接地址只有这些东西的第二位,但让我们开始吧。

该线程建议用联接表替换一对多关系,因为否则,一对多方法“用不属于该实体的列填充许多副表,仅用于“链接” porpuses(原文如此)
‘。这种策略可能会在Hibernate层中产生干净的模型,但不幸的是,这会导致数据库损坏。

因为SQL只能断言子记录有一个父记录;没有办法强制父母必须有孩子的规则。因此,没有办法坚持要求表在联接表中具有条目,结果是有可能具有孤立的子记录,这正是外键旨在防止的。

我还有其他一些反对意见,但下一个最重要的反对意见是不适当。相交表旨在表示多对多关系。用它们表示一对多的关系会造成混乱,并且我喜欢过多的其他数据库对象。

因此,第二个方面是: 单向
一对多关联。这些问题是Hibernate默认情况下处理它们的特殊方式。如果我们在同一事务中插入一个父项和一个子项,则Hibernate插入子项记录,然后插入父项,然后使用父项的键更新子项。这需要可延期的外键约束(yuck!),也可能需要不可延期的非null约束(double
yuck)。

有两个解决方法。一种是使用双向的一对多关联。根据文档中的引用,这是最常见的方法。另一种方法是调整子对象的映射,但这有其自身的影响。

2020-06-20