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

2022-09-03 02:29:27

可能的重复:
休眠单向一对多关联 - 为什么连接表更好?

在Hibernate在线文档中,在7.2.3一对多节中,提到了:

外键上的单向一对多关联是一种不寻常的情况,不建议这样做。应改为将联接表用于此类关联。

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

谁能解释一下这个建议背后的原因?

以下是参考文档内容的链接: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)

应改为将联接表用于此类关联。


答案 1

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

这有两个方面:

  • 单向
  • 一对多

线程@CalmStorm已删除的答案仅链接到解决其中的第二个问题,但让我们从它开始。

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

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

我还有其他一些反对意见,但下一个最重要的反对意见是不恰当的。交集表用于表示多对多关系。使用它们来表示一对多关系是令人困惑的,并且需要太多额外的数据库对象来满足我的喜好。

所以,对于第二个方面:单向的一对多关联。这些问题的问题在于Hibernate默认处理它们的特殊方式。如果我们在同一事务中插入父项和子项,则 Hibernate 插入子记录,然后插入父项,然后使用父项的键更新子项。这需要可延迟的外键约束(yuck!),并且可能还需要可延迟的非空约束(双yuck)。

有几种解决方法。一种是使用双义词的一对多关联。根据您引用的文档中,这是最常见的方法。另一种方法是调整子对象的映射,但这有其自身的后果。


答案 2

推荐