我有一个大的数据库,我有实体的关系。这正是由于Doctrine 2手册中的以下注释:我需要在关系中存储额外的属性,因此关系成为一个实体。
通常我们对实体使用生成的id,对关系使用复合键。在这种情况下,实体是一个关系,所以选择有点复杂…
请注意,我在这里谈论的不是自然键。我正在使用一个复合键,它由id组成,id是在各自拥有的实体中使用自动增量策略创建的整数。
我看到了在关系实体上使用复合主键的一些缺点:
- 我需要在创建实体和它们的关系之间调用persist(在我可以将实体用作复合主键中的外键之前,在实体上生成键)。
- 要将其他实体关联到关系实体,我们需要在这些实体中再次为复合键中使用的id添加列。如果我要使用代理主键,我只需要一个列来保存那个id。
我也看到了一些的优点使用组合键例如:
- 它们消除了对某些连接查询的需要,相反,您可以构建查询来直接使用组合键提取信息。
但是最重要的参数现在使用组合键是:
- 当User和SomeEntity之间的关系被删除并稍后重新创建时(这种情况很可能发生在我们的应用程序模型中),我们也需要恢复对所有其他相关实体的访问权限。如果User和SomeEntity之间的关系是在代理主键上使用自动增量策略创建的。恢复的(新)关系将获得一个新的主键(id)。因此,相关实体(使用"旧"键存储)不再可访问。如果我在关系上使用复合键,我可以简单地恢复关系(它获得相同的复合键值),这样我就可以立即再次访问其他相关实体。
有没有人有过类似的经历?是否有其他解决方案使其正常工作。(在使用Doctrine ORM时)是否有我错过的重要缺点或优点?
我能想到的一种替代方法是向User SomeEntity关系添加状态。我们可以将状态更改为disabled, enabled,而不是删除条目。这样,我们可以使用代理键而不是组合键,因为条目永远不会被删除…
非常感谢您的反馈……
对于感兴趣的人,这里也有一个关于代理键与堆栈溢出上的组合键的很好的讨论:(点击)
我建议将您的两个外键设置为复合主键。
您的关联实体将由其两个关系的id标识。
理论上,Doctrine的UnitOfWork/CommitOrderCalculator应该能够以正确的顺序插入元素,因此,您不必处理持久化顺序。
您的映射在末尾看起来像这样(注释示例):
<?php
class UserGroup
{
/**
* @ORMManyToOne(targetEntity="User")
* @ORMId
**/
public $user;
/**
* @ORMManyToOne(targetEntity="Group")
* @ORMId
**/
public $group;
}