【发布时间】:2021-09-10 21:33:56
【问题描述】:
问题描述
我目前正在从事一个需要关系数据库进行存储的项目。 在考虑了一段时间的数据及其关系后,我遇到了一个非常重复的问题:
我遇到了实体 A 的通用数据模式,其中包含一些字段,例如名称、描述、值。该实体与实体 B 在多个 n-1 关系中连接。所以实体 B 在关系 rel1 中有 n 个实体 A,在关系 rel2 中有 n 个实体 A。
现在我正在尝试将此数据模型分解为关系数据库(例如 Postgres、MySQL)的模式。 经过一番研究,我还没有真正找到解决这个特定问题的“最佳”解决方案。
到目前为止我发现了一些类似的问题:
我的想法
所以我想到了可能的解决方案,我将在这里介绍:
1。重复表
实体 B 到实体 A 的关系对它有一定的意义。因此可以创建多个表(每个关系 1 个)。这将解决所有直接问题,但实质上是重复表,这意味着现在必须将更改反映到多个表(例如新列)。
2。引入类型列
我只能说“实体 B 与 n 个实体 A 相连”,而不是多个关系。此外,我将添加一个类型列,然后告诉我 A 属于哪个关系实体。我不确定这是如何用 Spring-Hibernate 等常见 ORM 表示的,以及这是否会引入我目前不知道的其他问题。
3。抽象实体A的共同属性
另一种选择是创建一个 ADetails 实体,它捆绑了实体 A 的所有属性。 然后,我将创建两个实体,它们代表每个关系,并以一对一的关系连接到 ADetails 实体。这将解决外键的解释问题,但可能开销太大。
我的问题
- 在中大型项目的背景下,这些解决方案是否可行?
- 是否有某些缺点可以排除一种特定方法?
- 还有其他(更好的)我没有想过的选择吗?
感谢您对此事的任何帮助。
编辑 1 - PPR(个人-政党-角色)
感谢 AntC 的建议。 PPR Description
我认为所描述的情况符合我的问题。 让我们分解一下:
实体 B 是一个事件。对于给定的参与者,只有一个事件可以使这更容易。所以从事件到参与者的关系是 1-n。
实体 A 可以描述为组、人员、组织,但考虑到我的情况,它们都具有相同的属性。因此,将它们分成单独的表感觉是错误的想法。
用类图说明情况: 一个事件(实体 B)包含 n 个组(实体 A)、n 个人员(实体 A)和 n 个组织(实体 A)。
如果我理解正确,建议如下:
- 在我的例子中,事件和参与者之间的关系是 1-n
- RefRoles 表代表 ParticipantType 列,该列描述参与者所属的关系(例如,它是客户还是事件服务的一部分)
- 因为我所有的组、人员和组织都具有相同的属性,所以此时唯一需要的表是参与者表
- 如果将来有个别属性,我会引入一个新表(例如 People),以 1-1 关系引用参与者。
- 如果要添加多个表,则多个1-1关系的外键是互斥的(因此参与者只能有一个Group/Person/Organization)
AntC 和 Christian Beikov 提出的解决方案
拆分表确实有意义,同时将公共属性保留在一个表中。 目前没有单独的属性,但不再需要类型列,因为可以使用外键来查看实体属于哪个关系。
我为此创建了一个小例子:
- 一个活动存在 3 种类型(以前的类型列)人员:工作人员、VIP、访客
- 公共属性以 1-1 关系映射到 person 表。
- 为简单起见:每个人(员工、贵宾、访客)只能参加一个活动。 (在更高级的例子中是 n-m-relationship)
在我看来,这种方法比类型列要好。 它还解决了以后必须根据应用程序中的实体类型来解释实体的问题。也可以在 ORM (see this question) 中解析类型列,但如果您使用的 ORM 不支持解析,这种方法可以避免麻烦。
【问题讨论】:
-
这是一个非常高级的q。你能说一下
A, B是什么以及它们之间关系的本质吗?我想你可能在谈论 PPR(Person-Party-Role)结构——例如,同一个人可以是客户、供应商、员工、代理、其中一个的家庭成员等中的任何一个。databaseanswers.org/data_models/parties_roles_and_customers/…跨度> -
感谢您的建议。我添加了一些说明(参见编辑 1)。
-
我想你已经开始了。您可能需要一个桥接表 Person-event-role,请参阅此答案:stackoverflow.com/a/68171353/2840542。与该答案不同,您可能将同一个人以不同的角色链接到同一事件(桥中的多个记录),然后桥接表的事件角色形成其键。
标签: database hibernate orm relational-database