【问题标题】:Why do Hibernate docs recommend to use a join table for a one-to-many relation?为什么 Hibernate 文档建议将连接表用于一对多关系?
【发布时间】:2011-07-12 15:12:02
【问题描述】:

我认为在数据库中建模一对多关系的常用方法是通过外键关系(即一个客户有很多订单 -> 订单表获得对客户表的 FK 引用)。

但是,Hibernate 建议使用连接表来为此类关系建模:

在所拥有的中使用外键列的单向一对多 实体并不常见,也不是很推荐。我们强烈 建议您对这种关联使用连接表(如 在下一节中解释)。这种关联被描述 通过@JoinColumn。

http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html#entity-mapping-association

为什么“不推荐”。我认为使用 FK 是标准,而连接表仅用于多对多关系?

我不喜欢创建连接表,因为数据模型看起来像是多对多的关系,而实际上它是一对多的。

Hibernate 文档中此建议的原因是什么?

【问题讨论】:

标签: hibernate database-design foreign-key-relationship


【解决方案1】:

这个问题已在 Hibernate 论坛上提出并回答:https://forum.hibernate.org/viewtopic.php?t=954178&highlight=unidirectional+null+foriegn+foreign+key。这似乎不是 DB 设计的问题,而是 Hibernate 的功能问题。

【讨论】:

    【解决方案2】:

    您拥有 postet 的文档中的引用描述了 单向 @OneToMany 关联,这是另一回事。在这样的关联中,您只有 Customer 对 Orders 的引用,反之则没有。因此,应该使用连接表来映射这种关联,其中包含每个客户的订单集合。

    我猜您正在考虑的关联更可能是 @ManyToOne 关联,具有从 Order 到 Customer 的引用。

    请注意,如果要建模双向关联,可以使用@OneToMany 注解中的“mappedBy”属性。

    【讨论】:

    • 抱歉,无法关注您。是的,我在考虑只引用“客户->(订单列表)”。你指的是什么“这是一个不同的东西”?我想我需要一个一对多的关联,这就是我引用@OneToMany 部分的原因。
    • 我怀疑您正在考虑的是一种 双向 关系,其中 Order 具有标识其拥有的 Customer 的属性,而 Customer 具有列出其拥有的 Orders 的属性。在这种情况下,关于 单向 关系的评论不适用,外键很好。
    • 我认为针对单向一对多的外键的警告是存在的,因为它涉及到表中有一个列没有映射到相应实体中的任何内容,这有点奇怪.该列缺少映射表明该关系不是 Order 的固有部分,在这种情况下,为什么该列在 Order 的表中?
    • 因为它不是一个答案,只是乔治完美答案的一个小补充。
    【解决方案3】:

    我不能与任何权威人士交谈,但我一直认为,对于 单向 关系,您的订单更有可能处于多个此类关系的接收端。这也增加了 Order 在其中一些列中具有空值的可能性,因为 Order 已经创建,但是可以引用 Order 的其他对象要么还不存在,要么永远不会存在。就这一点而言,将 FK 列移到另一个表是标准化的问题。还有一个事实是它更好地反映了对象关系。在 Foo -> Bar 的单向一对一中,您希望在 Foo 中找到 FK,而不是在 Bar 中,因为这是对象模型中的所有权所在。这同样适用于来自客户 -> 订单的单一一对多。查看对象模型,您不会期望在 Order 中看到所有权,因此也不会在 Order 表中。

    【讨论】:

      【解决方案4】:

      Hibernate 文档中的上一部分介绍了双向一对多关系,并描述了您可能习惯的内容,以及多实体上的标准外键。正如其他人所说,仅当您明确需要单向关系时,此答案才合适。

      如果多方一定不知道这种关系,你只会想要单向性。这意味着多方面的类几乎按照定义不能具有表示关系的属性。所以把这个问题想象成问“我如何在不使用正常方法的情况下表示一对多关系”。

      想要这样的单向关系当然有些不寻常,但我可以看到您可能出于解耦、安全、审计或不变性的原因需要它。例如,假设您正在对临床试验进行建模,并且您的课程是患者和药物,并且在试验期间您将一组药物中的一种分配给每位患者。您希望在 Patient 上运行的任何逻辑与分配给它们的 Medication 完全解耦。因此,您无需像通常那样使用 Patient.setMedication(),而是创建连接类 MedicationPatientMap 并调用 drug.getMedicationPatientMap().addPatient(patient)。然后,您可以通过药物方面的逻辑控制对患者的一对多关系的药物访问。

      我不认为 Customer-Order 是一个很好的例子,因为通常我们的订单心理模型期望客户可以通过它联系到。事实上,大多数时候你不是

      【讨论】:

        猜你喜欢
        • 2022-01-20
        • 1970-01-01
        • 2014-09-12
        • 1970-01-01
        • 2017-05-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-04
        相关资源
        最近更新 更多