1

我有一个大型数据库,其中有关系实体。这正是因为 Doctrine 2 手册中的以下注释:我需要在我们的关系中存储额外的属性,因此关系成为一个实体。

通常我们为实体使用生成的 id,为关系使用复合键。在这种情况下,实体是一种关系,因此选择有点复杂......

请注意,我在这里不是在谈论自然键。我正在使用一个复合键,它由 id 组成,这些 id 是在各自拥有的实体中使用自动增量策略创建的整数。

我看到在关系实体上使用复合主键的一些缺点:

  • 我需要在创建实体及其关系之间调用persist(在我可以将它用作复合主键中的外键之前生成实体上的键)。
  • 要将其他实体与关系实体相关联,我们需要在这些实体中再次为复合键中使用的 id 添加列。如果我要使用代理主键,我只需要一列来保存那个 id。

我还看到了使用复合键的一些优点,例如:

  • 它们消除了对某些连接查询的需要,相反,您可以构建查询以使用复合键直接提取信息。

但目前使用复合键最重要的论点如下:

  • 当 User 和 SomeEntity 之间的关系被删除并随后再次创建时(这种情况很可能发生在我们的应用程序模型中),我们也需要恢复对所有其他相关实体的访问。如果 User 和 SomeEntity 之间的关系是使用代理主键上的自动增量策略创建的。恢复的(新)关系将获得一个新的主键(id)。因此,相关实体(使用“旧”键存储)不再可访问。如果我在关系上使用复合键,我可以简单地恢复关系(它获得相同的复合键值)并且我可以立即再次访问其他相关实体。

有没有遇到过类似情况的人?是否有其他解决方案可以使其正常工作。我错过了任何重要的缺点或优点(使用 Doctrine ORM 时)。

我能想到的另一种选择是向 User SomeEntity 关系添加一个状态。我们可以将状态更改为禁用、启用,而不是删除条目。通过这种方式,我们可以使用代理键而不是复合键,因为该条目永远不会被删除......

非常感谢您的反馈...

对于感兴趣的人,这里还对 Stack Overflow 上的代理键与复合键进行了很好的讨论:(单击)

4

1 回答 1

1

我建议将您的两个外键设为复合主键。

您的关联实体将由其两个关系的 id 标识。

从理论上讲,Doctrine 的 UnitOfWork/CommitOrderCalculator 应该能够以正确的顺序插入元素,因此,您不必处理持久顺序。

您的映射最后将如下所示(注释示例):

<?php

class UserGroup
{
    /**
      * @ORM\ManyToOne(targetEntity="User")
      * @ORM\Id
     **/
    public $user;

    /**
      * @ORM\ManyToOne(targetEntity="Group")
      * @ORM\Id
     **/
    public $group;
}
于 2013-05-17T14:32:04.840 回答