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

DDD:在PostgreSQL中建模聚合实体的唯一全局/本地id,postgresql,domain-driven-design,aggregate,uniqueidentifier,Postgresql,Domain Driven Design,Aggregate,Uniqueidentifier,我读过Eric Evans的领域驱动设计书,我一直在尝试应用其中的一些概念 在他的书中,Eric谈到了聚合以及聚合根应该如何具有唯一的全局id,而聚合成员应该具有唯一的本地id。我一直试图将这一概念应用到我的数据库表中,我遇到了一些问题 我的PostgreSQL数据库中有两个表:facilities和employees,在这两个表中,可以将员工分配到单个设施 过去,我会将员工表安排如下: CREATE TABLE "employees" ( "employeeid" serial NOT

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

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

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

过去,我会将员工表安排如下:

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员工ID:1,设施ID:1 员工B员工ID:2,设施ID:1 员工C员工ID:1,设施ID:2

其中A、B和C是3名不同的员工,并且。。。 将员工D添加到设施1将为他提供密钥employeeid:3,设施ID:1 将雇员E添加到设施2将为他提供密钥employeeid:2,facilityid:2

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

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

我可能会为每个设施创建一个新的序列来管理员工ID,但我担心最终会有数千个序列需要管理,如果设施被删除,会有删除这些序列的程序。这有什么问题吗?我觉得它很重


我应该采取哪种方法?有什么我遗漏的吗?

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


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

我猜您在这里强调了聚合根的概念。根据我对员工建模的理解,员工几乎总是一个聚合根,可能被另一个聚合根设施引用


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

我对您试图实现的目标以及这与DDD的关系感到有点困惑。您首先将一对多关系描述为需求,然后在“这就是我要寻找的:”中显示多对多关系的数据。您是否要在这个有界上下文之外公开雇员实体?通常,根据我的经验,全局ID和本地ID之间的区别在于简单地将全局ID设置为UUID或GUID。然后你就知道这个id在有界的上下文中是唯一的。我编辑了我的问题,希望能让它不那么模棱两可。我想要的关系是一对多的关系,雇员实体不会暴露在有界上下文之外。我主要是在寻找产生这些员工ID的最佳方法。