Orm 工作单位的实际使用&;存储库模式

Orm 工作单位的实际使用&;存储库模式,orm,domain-driven-design,repository-pattern,unit-of-work,domain-model,Orm,Domain Driven Design,Repository Pattern,Unit Of Work,Domain Model,我正在构建一个ORM,并试图找出每个模式的确切职责。假设我想在两个帐户之间转账,使用工作单元管理单个数据库事务中的更新。 以下方法正确吗 从存储库中获取它们 将它们附加到我的工作单元 是否执行业务事务和提交 例如: from = acccountRepository.find(fromAccountId); to = accountRepository.find(toAccountId); unitOfWork.attach(from); unitOfWork.attach(to);

我正在构建一个ORM,并试图找出每个模式的确切职责。假设我想在两个帐户之间转账,使用工作单元管理单个数据库事务中的更新。 以下方法正确吗

  • 从存储库中获取它们
  • 将它们附加到我的工作单元
  • 是否执行业务事务和提交
  • 例如:

    from = acccountRepository.find(fromAccountId);
    to = accountRepository.find(toAccountId);
    
    unitOfWork.attach(from);
    unitOfWork.attach(to);    
    
    unitOfWork.begin();
    from.withdraw(amount);
    to.deposit(amount);
    unitOfWork.commit();
    
    如本例所示,工作单元和存储库是否应单独使用,或者:

    • 工作单元是否应该在内部使用存储库并能够加载对象
    • 。。。或者存储库是否应该在内部使用工作单元并自动附加任何加载的实体
    欢迎大家发表意见

    好问题

    取决于你的工作边界是什么。如果它们要跨越多个存储库,那么您可能必须创建另一个抽象以确保覆盖多个存储库。它就像一个在领域驱动设计中定义的小“服务”层

    如果您的工作单元几乎是每个存储库,那么我会选择第二个选项


    然而,我的问题是,在编写ORM时,如何担心存储库?它们将由您工作单元的消费者定义和使用,对吗?如果是这样的话,您别无选择,只能提供一个工作单元,您的消费者将不得不将存储库与您的工作单元一起登记,并且还将负责控制工作单元的边界。不是吗?

    当存储库在内部使用UoW时,我建议您使用这种方法。这种方法有一些优点,特别是对于web应用程序

    在web应用程序中,推荐的使用UoW的模式是每个HTTP请求的工作单元(会话)。所以,如果您的存储库将共享UoW,您将能够对其他存储库(如多个聚合引用的数据字典)请求的对象使用一级缓存(使用标识映射)。此外,您只需提交一个事务,而不必提交多个事务,所以它在性能方面会工作得更好


    您可以看一看Java/.NET世界中成熟的ORM的Hibernate/NHibernate源代码。

    简单的回答是,存储库将以某种方式使用UoW,但我认为这些模式之间的关系没有最初看起来那么具体。工作单元的目标是创建一种基本上将一组数据库相关函数组合在一起的方法,以便它们可以作为一个原子单元执行。使用UoW时创建的边界与事务创建的边界之间通常存在关系,但这种关系更为一致

    另一方面,存储库模式是一种在聚合根上创建类似于集合的抽象的方法。通常,您在存储库中看到的各种事情都与查询或查找聚合根的实例有关。一个更有趣的问题(而且没有一个答案)是,添加处理聚合查询以外的内容的方法是否有意义。一方面,可能存在一些有效的情况,其中您的操作将应用于多个聚合。另一方面,如果您在多个聚合上执行操作,那么您实际上是在另一个聚合上执行单个操作。如果您只是查询数据,我不知道您是否真的需要创建UoW隐含的边界。这一切都归结到域和它是如何建模的

    这两种模式在非常不同的抽象级别上进行处理,工作单元的参与也将取决于聚合的建模方式。聚合可能希望将与持久性相关的工作委托给其管理的实体,或者在聚合和实际ORM之间可能存在另一层抽象。如果您的聚合/实体本身正在处理持久性,那么存储库也可以管理该持久性。如果没有,那么在存储库中包含UoW是没有意义的


    如果您想在组织之外创建一些供一般公众使用的东西,那么我建议您创建存储库接口/基本实现,使它们能够直接与您的ORM交互,或者不依赖于ORM用户的需要。如果这是内部的,并且您正在Aggregates.Entities中执行持久性工作,那么您的存储库使用UoW是有意义的。对于通用存储库来说,从存储库实现中提供对UoW对象的访问是有意义的,这样可以确保UoW对象被适当地初始化和处置。注意,有时您可能希望在一个UoW边界内使用多个存储库,因此在这种情况下,您希望能够将一个已准备就绪的UoW传递到存储库。

    只是好奇,为什么要在有好几种ORM的情况下构建ORM呢?只是尝试将ORM的最佳实践应用到PHP中。已经有一些了,但并不完全符合我的期望。感谢我发现了这样一个问题+1谢谢。实际上,我的计划是为所有这些模式定义一个干净的接口,以及一个基本实现,它的目标是非常通用,并适应我们日常工作的大多数情况。我已经有了一个有效的实现,模型和数据映射器以及映射器注册表,它提供了对单个类中所有映射器的访问;但我正试图突破界限,为保存身份图的存储库提供支持,支持标准搜索,并支持W