存储库的预期行为

时间:2011-05-18 19:51:01

标签: orm domain-driven-design unit-of-work ddd-repositories poeaa

我正在编写一个ORM,并且不确定存储库的预期行为,或者更确切地说,是存储库和工作单元之间的边界。 根据我的理解,存储库可能如下所示:

interface IPersonRepository
{
    public function find(Criteria criteria);
    public function add(Person person);
    public function delete(Person person);
}

根据福勒( PoEAA ,第322页):

  

存储库在域和数据映射层之间进行调解,其作用类似于内存中的域对象集合。 [...]对象可以添加到存储库或从存储库中删除,因为它们可以从简单的对象集合中添加。

这意味着以下测试应该有效(假设我们已经持有一个Person,其姓氏为Fowler):

collection = repository.find(lastnameEqualsFowlerCriteria);
person = collection[0];

assertEquals(person.lastname, "Fowler");

person.lastname = "Evans";
newCollection = repository.find(lastnameEqualsFowlerCriteria);

assertFalse(newCollection.contains(person));

这意味着当映射到数据库时,即使没有在某处调用显式的save()方法,Person模型也必须由Repository自动保留,以便下一个查询返回正确的集合包含原始人。

但是,工作单位的作用,不是决定哪个模型能够持久存储到数据库,何时?

在上面的实现中,Repository必须决定在接收另一个find()调用时保留先前检索的Person,以便结果与修改一致。但是如果没有发出其他的find()调用,模型就不会被隐含地持久存在。

在工作单元的上下文中,它实际上不是问题,因为我们可以在开始时启动事务,并在需要时将任何插入回滚到数据库。 但是当单独使用时,这个Repository不能导致意外的,不可预测的行为吗?

2 个答案:

答案 0 :(得分:1)

  

知识库在中间进行调解   行动的域和数据映射层   像内存中的域对象   采集。 [...]可以添加对象   从存储库中删除和删除   他们可以从一个简单的集合   对象。

这并不意味着您不需要保存方法。您仍然需要将更改显式提交到存储。

请参阅The Unit Of Work Pattern And Persistence Ignorance

public interface IUnitOfWork {
  void MarkDirty(object entity);
  void MarkNew(object entity);
  void MarkDeleted(object entity);
  void Commit();
  void Rollback();
}

在某种程度上,您可以将工作单元视为转储所有交易处理代码的地方。工作单位的职责是:

  • 管理交易。
  • 订购数据库插入,删除和更新。
  • 防止重复更新。在使用Unit of Work对象的单个内部中,代码的不同部分可以将相同的Invoice对象标记为已更改,但Unit of Work类将仅向数据库发出单个UPDATE命令

答案 1 :(得分:0)

我认为你要问的是:http://martinfowler.com/eaaCatalog/identityMap.html

存储库应该在内存中保留已获取的对象,并且不应该从持久性存储中检索该实体的所有后续调用,因此您的示例应该可以正常工作。