DDD:在PostgreSQL中为聚合实体的唯一全局/本地ID建模

时间:2012-04-07 07:20:45

标签: postgresql domain-driven-design aggregate uniqueidentifier

我读过埃里克埃文斯的领域驱动设计书,我一直试图应用一些概念。

在他的书中,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(员工:1,设施:1)
员工B(员工人数:2人,工资:1人)
员工C(employeeid:1,facilityid:2)

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


我认为有两种方法可以实现这一目标:

  1. 我可以使用触发器或存储过程自动生成新的employeeid,并将最后的id存储到另一个表中的每个工具中,以便更快地访问,但我担心并发问题并最终与来自同一工厂的2名员工相同的身份。

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

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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

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

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