我们有几个聚合根,有两种主要的识别方法:
拥有基于整数的私有标识符和基于字符串的公共标识符有几个原因 - 例如,数据库执行得更好(8字节整数而不是可变长度字符串)并且公共标识符很难猜测。
但是,类在内部使用基于整数的标识符相互引用,如果基于整数的标识符为0,则表示该对象尚未存储到数据库中。这会产生一个问题,因为实体在 之后才能引用其他聚合根。
如何解决这个问题,或者我对持久性无知的理解存在缺陷?
关于基于字符串的标识符的编辑
基于字符串的标识符由存储库生成,连接到PostgreSQL数据库,该数据库生成标识符以确保它不会与数据库中当前的任何内容冲突。例如:
class Customer {
public function __construct($customerKey, $customerId, $name) {
$this->customerKey = $customerKey;
$this->customerId = $customerId;
$this->name = $name;
}
}
function test(Repository $repository, UnitOfWork $unitOfWork) {
$customer = new Customer(0, $repository->generateCustomerId(), "John Doe");
// $customer->customerKey == 0
$unitOfWork->saveCustomer($customer);
// $customer->customerKey != 0
}
我假设可以使用相同的概念来创建具有非0的基于整数的键的实体,并且工作单元可以使用它在数据库中不存在的事实作为原因INSERT而不是UPDATE。上面的test()
函数将变为:
function test(Repository $repository, UnitOfWork $unitOfWork) {
$customer = new Customer($repository->generateCustomerKey(), $repository->generateCustomerId(), "John Doe");
// $customer->customerKey != 0
$unitOfWork->saveCustomer($customer);
// $customer->customerKey still != 0
}
但是,鉴于上述情况,如果工作单元未按正确顺序保存数据库对象,则可能会发生错误。是解决这个问题的方法,以确保工作单元以正确的顺序保存实体吗?
我希望以上编辑能够澄清我的情况。
答案 0 :(得分:2)
将聚合视为一致性边界是一种很好的方法。换句话说,两个不同的聚合具有不同的生命周期,你应该避免在同一个事务中将它们的命运捆绑在一起。从这个公理中你可以安全地说明,当从另一个聚合B的角度来看时,没有聚合A的ID将为0,因为创建A的事务尚未完成且B不可见,或者它已完成和A有一个ID。
关于双重身份,我宁愿拥有语言生成的字符串ID而不是数据库,因为我想提出一个唯一的ID会暗示一个事务,可能跨多个表。语言通常可以生成具有良好熵的唯一字符串。