在域驱动设计中,存储库模式是否维护对对象的引用


In Domain Driven Design, does the Repository pattern maintain a reference to the objects?

我知道存储库模式抽象了域对象的持久性,允许开发人员从持久存储中读取/写入/删除对象,而无需知道对象是如何存储的(SQL,NoSQL,平面文件等)。我非常喜欢存储库模式,并发现它在许多情况下都运行良好,例如,从持久性逻辑中抽象业务逻辑,允许在适当的情况下延迟加载对象等。

但是,我不清楚的是存储库对象是否维护对所有对象的引用?例如:

Repository repository;
std::shared_ptr<Person> pPerson = repository.retrievePersonById("bob");
p->updateDetails("Bob", "the Builder");
repository.savePerson(p);
  1. 在上面的假设C++示例中,repository是否应该维护对返回的Person实例的引用?是的 - 感谢纪尧姆31 的内存类比
  2. 如果问题 1 的答案是"是",repository何时以及如何删除该Person实例?据推测,这是引用计数达到零时。
  3. 如果 Q1 的答案是否定的,那么当另一个区域想要访问同一对象,但由于repository不再存储对它的内部引用,它会从数据库中冻结一个新副本,并且当您真正应该引用同一实例时,您实际上有两个Person实例时,您如何处理这种情况?鉴于 Q1 的答案是"是",那么存储库始终维护一个引用,因此应始终返回相同的对象

我实际上正在编写一个PHP应用程序,尽管上面的例子是C++的。

对于存储库来说,更合适的比喻可能是它是内存中对象集合的错觉。从任何 OO 语言中获取基本集合类型。如果从该集合中获取元素并修改该元素,则通常不必在之后将其保存回集合,因为它从未停止在集合中。

存储库也是如此 - 它提供对象,可以将对象添加到自身,但不公开任何用于将修改保存到底层存储的功能。事实上,这一切都是为了隐藏底层存储的存在。它也不会公开任何方法来"更新"实体的状态,因为它服务的实体在内存中,您可以自由修改它,它永远不会不同步。

如果存储库不干涉事务管理和提交工作单元,那也会更好。您应该将其委托给客户端(请参阅领域驱动设计第 156 页)。

为了回答您的问题,在业务事务中,您不应该假设存储库返回的对象的新鲜度。它们只是反映了某些实体在某个时间点的状态,您所要做的就是按原样使用它们。在更全局的层面上,一些外部机制(通常是ORM工具)将为您提供管理如何将您的小业务交易与其他交易隔离的能力,通常以工作单元实现的形式。刷新对数据库的更改和处理潜在的过时实体问题不是每个存储库的查询决策,而是一个更全局的业务事务级别的决策,只有在您决定用例已完成并且想要提交它时才应该发生。