17

我正在构建一个ORM,并试图找出每个模式的确切职责。假设我想在两个帐户之间转移资金,使用Unit Of Work来管理单个数据库事务中的更新。 以下方法是否正确?工作单元和存储库模式的实际用法

  1. 从系统信息库
  2. 让他们将它们连接到我单位工作
  3. 做生意交易&承诺?

实施例:

from = acccountRepository.find(fromAccountId); 
to = accountRepository.find(toAccountId); 

unitOfWork.attach(from); 
unitOfWork.attach(to);  

unitOfWork.begin(); 
from.withdraw(amount); 
to.deposit(amount); 
unitOfWork.commit(); 

应,如在这个例子中,单元的工作和存储库可以独立使用,或:

  • 如果该单元的工作在内部使用的储存库并有能力加载对象?
  • ...或者库应该在内部使用Unit Of Work并自动附加任何加载的实体?

欢迎您发表评论!

+3

只是好奇,为什么建立ORM时,有几个好的那里呢? – 2011-05-19 10:31:56

+1

试图将ORM最佳实践应用于PHP。已经有几个了,但并不完全符合我的期望。 – Benjamin 2011-05-19 11:06:44

+1

+1好问题。 – Nilesh 2011-05-19 13:50:05

回答

16

简短的回答可能是仓库会以某种方式使用UoW,但我认为这些模式之间的关系比起初看起来不那么具体。 Unit Of Work的目标是创建一种方法,将一组数据库相关功能基本上组合在一起,以便它们可以作为原子单元执行。使用UoW时创建的边界与交易创建的边界之间经常存在关系,但这种关系更为巧合。

另一方面,存储库模式是一种创建类似集合根集合的抽象的方法。通常情况下,您在存储库中看到的种类与查询或查找聚合根目录的实例有关。一个更有趣的问题(以及没有单一答案的问题)是添加处理除聚合查询之外的其他方法是否合理。一方面,您可能会遇到一些有效的情况,即您的操作适用于多个聚合。另一方面,可能会争辩说,如果您在多个Aggregate上执行操作,则实际上是在另一个Aggregate上执行单个操作。如果你只是查询数据,我不知道你是否真的需要创建UoW所隐含的界限。这一切都归结到域以及它是如何建模的。

这两种模式处理的抽象程度非常不同,工作单元的参与取决于集合体是如何建模的。聚集可能希望将与持久性相关的工作委托给其管理的实体,或者聚集与实际ORM之间可能存在另一个抽象层。如果您的Aggregates/Entities本身正在处理持久性,那么对于Repositories来说,也可以管理持久性。如果没有,那么在您的Repository中包含UoW是没有意义的。

如果您希望为组织外的一般公共消费创建东西,那么我会建议您创建您的存储库接口/基础实施,以允许它们直接与您的ORM进行交互,而不取决于ORM用户的需求。如果这是内部的,并且您在Aggregates.Entities中正在执行持久性工作,那么您的Repository利用您的UoW是有意义的。对于一个通用的Repository,从Repository实现中提供对UoW对象的访问是有意义的,这可以确保它被适当地初始化和处置。在这个说明中,也会有些时候您可能想在单个UoW边界内使用多个存储库,因此在这种情况下,您希望能够将已启动的UoW传递到存储库。

+0

感谢您的完整答案。作为结论,没有“最好”的方法来做到这一点,这是ORM全球范围内的选择问题。 – Benjamin 2011-05-29 16:10:58

2

好问题!

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

如果你的工作单元将会非常多,那么我会选择第二个选项。

但是,我的问题是,你在编写ORM时如何担心仓库?它们将由你的工作单位的消费者定义和使用吗?如果是这样,你别无选择,只能提供一个工作单元,你的消费者将不得不把你的工作单位列入工作单位,并且还要负责控制工作单元的界限。不是吗?

+0

谢谢尼莱什。实际上,我的计划是为所有这些模式定义一个干净的界面,以及一个基本的实现,其目标是非常通用,并适应我们日常工作的大部分情况。我已经有了一个工作实现,模型和数据映射器以及一个映射器注册表,可以在一个类中提供对所有映射器的访问;但我试图推动界限为持有标识映射的存储库提供支持,支持标准搜索以及工作单元,以管理对数据库的更新和处理事务。 – Benjamin 2011-05-19 14:13:31

+0

对不起,如此详细,我需要更多的空间:) 所以我想找到一个通用的想法,如何把它放在一起!非常感谢您的帮助。 – Benjamin 2011-05-19 14:17:43

4

我建议你在内部使用UoW时使用方法。这种方法有一些优点,特别是对于Web应用程序。

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

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

+0

感谢您分享您的观点! – Benjamin 2011-05-29 16:13:17

相关问题