java - 为什么建议避免外键上的单向一对多关联?

标签 java sql hibernate rdbms

<分区>

Possible Duplicate:
Hibernate unidirectional one to many association - why is a join table better?

在 Hibernate 在线文档中,在 7.2.3 一对多部分下提到:

unidirectional one-to-many association on a foreign key is an unusual case, and is not recommended. You should instead use a join table for this kind of association.

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

谁能解释推荐背后的理由?

这里是引用文档内容的链接:7.2.3. One-to-many

我把实际内容复制粘贴到这里:

A unidirectional one-to-many association on a foreign key is an unusual case, and is not recommended.

<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)

You should instead use a join table for this kind of association.

最佳答案

unidirectional one-to-many association on a foreign key is an unusual case, and is not recommended.

这有两个方面:

  • 单向
  • 一对多

thread @CalmStorm 删除的答案链接仅指向其中的第二个问题,但让我们从它开始。

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

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

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

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

对此有一些解决方法。一种是使用双向一对多关联。根据in the document you cite这是最常见的方法。另一种方法是调整子对象的映射,但这有其自身的后果。

关于java - 为什么建议避免外键上的单向一对多关联?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2092611/

相关文章:

java - Hibernate实体模式@Table(schema ="<schema-name>"),获取表未找到异常

java - 如何重命名 slack app 主页选项卡并更改打开选项卡的顺序

java - 常见 nlp 任务的效率

mysql - SQL:无法删除或更新父行:外键约束失败

hibernate - 防止删除级联到实体实例

java - hibernate @OneToOne 给出错误

java - 简单的 Java boolean 值不工作

java - 将参数动态设置为 JDBC 中的准备语句

MySQL如何选择每个组的第一行计数

php - 按 mysql 选项分组