2

我读过 Eric Evans 的领域驱动设计一书,并且一直在尝试应用其中的一些概念。

在他的书中,Eric 谈到了聚合以及聚合根应该如何具有唯一的全局 ID,而聚合成员应该具有唯一的本地 ID。我一直在尝试将该概念应用于我的数据库表,但遇到了一些问题。

我的 PostgreSQL 数据库中有两个表:设施和员工,可以将员工分配到单个设施。


过去,我会按如下方式布置员工表:

CREATE TABLE "employees" (
  "employeeid"  serial NOT NULL PRIMARY KEY,
  "facilityid"  integer NOT NULL,
  ...
  FOREIGN KEY ("facilityid") REFERENCES "facilities" ("facilityid")
);

其中employeeid 是一个全球唯一的ID。然后,我将在后端添加代码以进行访问控制验证,防止一个设施的用户访问与其他设施相关的行。我有一种感觉,这可能不是最安全的方法。



我现在考虑的是这种布局:

CREATE TABLE "employees" (
  "employeeid"  integer NOT NULL,
  "facilityid"  integer NOT NULL,
  ...
  PRIMARY KEY ("employeeid", "facilityid"),
  FOREIGN KEY ("facilityid") REFERENCES "facilities" ("facilityid")
);

其中employeeid 对于给定的facilityid 是唯一的(本地),但需要与facilityid 配对才能在全球范围内唯一。

具体来说,这就是我要找的:

员工 A (employeeid: 1, facilityid: 1)
员工 B (employeeid: 2, facilityid: 1)
员工 C (employeeid: 1, facilityid: 2)

其中 A、B 和 C 是 3 名不同的员工,并且...
将员工 D 添加到设施 1 会给他钥匙(employeeid:3,facilityid:1)
将员工 E 添加到设施 2 会给他钥匙(employeeid: 2、facilityid:2)


我看到了两种实现这一目标的方法:

  1. 我可以使用触发器或存储过程来自动生成新的员工 ID,并将每个设施的最后一个 ID 存储在另一个表中以便更快地访问,但我担心并发问题并最终导致来自同一设施的 2 名员工具有相同的 ID。

  2. 我可以为每个设施创建一个新序列来管理员工 ID,但我担心最终需要管理数千个序列,并且在删除设施的情况下会删除这些序列。这有什么问题吗?对我来说似乎很重。

我应该采取哪种方法?有什么我错过的吗?

4

2 回答 2

1

我猜你在这里过分强调了聚合根的概念。根据我对员工建模的理解(取决于您的上下文),员工几乎总是一个聚合根,可能被另一个聚合根设施引用。

员工和设施几乎总是拥有自然密钥。对于员工来说,这通常是一些员工 ID(印在员工身份证上,或至少在人力资源软件系统中维护),设施也有这个自然键,几乎总是包含一些位置部分和一些数字,如“ MUC-1 ”设施 1 位于慕尼黑。但这一切都取决于您的上下文。如果员工和设施拥有这些自然键,您的数据库模型应该非常清晰。

于 2012-04-08T07:50:44.810 回答
1

我从你的问题推断你将为所有设施运行一个数据库,或者至少如果你有一个本地数据库作为每个设施的“主”,那么数据需要在一个中央数据库中组合而不会发生冲突.

我会将 facilityid 设为主键的高阶部分。您可能可以使用一种简单的SELECT max(employeeid) + 1 ... WHERE facilityid = n方法分配新员工编号,因为将员工添加到任何一个设施可能不会从多个并发源每秒发生数百次。这可能会导致偶尔的序列化失败,但我认为任何数据库访问都应该通过一个能够识别这些并自动重试事务的框架。

于 2012-04-07T15:08:35.093 回答