在我的实践中,在同一类中相同类型的字段的情况下,将 OOP 方法映射到关系数据库经常会出现问题。我无法理解如何以最有效的方式解决这样的问题。
更详细的例子:
我有一个Person
具有字段address
和workAddress
. 此外,两个子实体具有相同的字段集。
在代码中它看起来像这样(伪代码):
class Person
Address address
Address workAddress
如何使用编程语言来实现这一点很清楚。有一个问题是如何在数据库中制作它。例如,我可以这样做(伪sql
):
CREATE TABLE address (id SERIAL PRIMARY KEY);
CREATE TABLE PERSON (
id SERIAL PRIMARY KEY,
address FOREIGN KEY (address.id),
workdAddress FOREIGN KEY (address.id)
);
这会起作用,但从数据库理论的角度来看,它并不完全正确。毕竟,我们将有一个一对多的地址人端。甚至两次。
你也可以这样:
CREATE TABLE PERSON (
id SERIAL PRIMARY KEY
);
CREATE TABLE address_type (
id SERIAL PRIMARY KEY,
name VARCHAR(50)
);
CREATE TABLE address (
id SERIAL PRIMARY KEY,
person_id FORIGN KEY(person.id),
address_type FORIGN KEY (address_type.id)
);
在这里,我们从关系模型的角度得到了正确的解决方案,但对于 OOP 来说却是一个非常糟糕的解决方案。这里的缺点是:JOIN
带有类型的附加表,在代码中使用它很不方便(您需要遍历所有地址才能找到正确的地址或补充选择)。
我一直在寻找最流行的解决方案ORM
- Hibernate
. 我没有找到任何东西来解决这样的问题(也许我看起来很糟糕)。
是否有任何共同的做法、工具或机制来处理此类问题?
你确定你有一对多吗?特别是有工作地址?或者您出于其他原因(安全等)故意复制数据
如果没有重复的理由,那么您可以使用关联类将其建模为多对多
我明白问题是选择:
两种选择都不错,都有存在的权利。选择哪一个取决于要解决的问题的要求。
如果两个表之间的链接类型是刚性固定的,在系统运行过程中不会改变,并且不提供进一步的扩展,则可以选择第一个选项。此外,此解决方案比第二种解决方案简单得多。
如果需要设置额外的关系参数(类型、可见性、可用性、多重性、优先级),并且提供了对这两个表的关系类型的灵活管理,则可以选择第二个选项。例如,理论上可以存储相关数据的变化历史。
关于特定地址方案 - 为简单起见,第一个选项非常合适。如果你突然需要存储地址变化的历史,那么第二种更合适。或者可能会突然出现其他类型的地址——例如,送货地址、注册地址、住所地址、邮政地址等。