数据映射器和存储库之间究竟有什么区别?

时间:2015-01-17 04:20:39

标签: orm repository repository-pattern datamapper domain-model

我一直在努力找出数据映射器和存储库之间的区别,但到目前为止我还没有。在我看来,专家程序员说“存储库是查询构造代码集中的映射层的另一个抽象层”。这似乎可以理解,但仍然有点抽象。我之前在stackoverflow上读过这篇文章,它让我更加困惑: How is the Data Mapper pattern different from the Repository Pattern?

我想我需要的是关于两种模式如何不同的简单解释和具体/实际示例,以及存储库对数据映射器不起作用的内容,反之亦然。你们中的任何人都知道一个关于说明数据映射器和存储库概念的好例子吗?如果它是相同的示例,只有一个使用数据映射器而另一个使用存储库会更好。谢谢,我非常感谢。到目前为止我仍然很困惑......

2 个答案:

答案 0 :(得分:17)

假设您的应用管理Person个对象,每个实例都有nameagejobTitle属性。

您希望保留此类对象,然后从持久性介质中检索并更新(例如,在他们的生日,增加日期)或删除。这些任务通常称为CRUD,来自创建,读取,更新和删除。

最好将“业务”逻辑与处理Person对象持久性的逻辑分开。这允许您更改持久性逻辑(例如,从数据库转到分布式文件系统),而不会影响业务逻辑。

您可以通过将所有持久性逻辑封装在Repository后面来实现此目的。假设的PersonRepository(或Repository<Person>)允许您编写如下代码:

Person johnDoe = personRepository.get(p=> p.name == "John Doe"); johnDoe.jobTitle = "IT Specialist"; personRepository.update(johnDoe);

这只是业务逻辑,并不关心对象的存储方式和位置。

Repository的另一端,您同时使用DataMapper和将功能描述(p=> p.name == "John Doe"中的查询转换为持久层理解的内容)的内容。

您的持久层可以是数据库,在这种情况下,DataMapper会将Person对象转换为PersonsTable中的行。然后,查询翻译器将功能查询转换为SELECT * FROM PersonsTable WHERE name == "John Doe"

另一个持久层可以是文件系统,也可以是另一种选择在PersonPersonAge两个表中存储PersonJobTitle个对象的数据库格式。

在后一种情况下,DataMapper的任务是将johnDoe对象转换为2行:一行用于PersonAge表,一行用于PersonJobTitle表。然后,查询逻辑需要将功能查询转换为两个表上的join。最后,DataMapper需要知道如何从查询结果中构造Person对象。

在大型复杂系统中,您希望使用可以独立开发和测试的小型,明确定义的小组件:

  • 业务逻辑在想要读取或保留对象时处理Repository,而不关心如何实现
  • Repository在想要读取/写入特定持久性媒体中的对象时处理DataMapper
  • 对于查询,Repository依赖于DataMapper提供的架构(例如,jobTitle列中的JobTitle列中找到PersonTable值表)但不适用于映射器的任何实现
  • 对于数据库持久性,DataMapper依赖于数据库层,使其免受Oracle / Sybase / MSSQL / OtherProvider详细信息的影响。

模式没有“不同”,它们只是暴露了不同的基本特征。

答案 1 :(得分:10)

我意识到这个答案有点迟了,但它可能会帮助将来偶然发现同样的问题并发现可用的答案并不能完全回答这个问题(当我第一次来到这个问题时在这个问题上)。

在阅读PoEAA(Martin Fowler)之后,我也无法识别数据映射器和存储库之间的区别。

我发现这两个概念最终归结为:

  • 存储库就像一个域对象集合,具有强大的查询功能(Evans,DDD)
  • 一个 DataMapper &#34;在对象和数据库之间移动数据,同时保持它们彼此独立以及映射器本身&#34; (福勒,PoEAA)

存储库是一个通用概念,不一定要将任何东西存储到数据库中,其主要功能是提供对域对象的集合(支持查询)访问(无论它们是否存在)从数据库得到的除了点之外)。存储库可能(通常会)包含DataMappers本身。

DataMappers 充当域对象和数据库之间的中间层,允许它们独立发展而不依赖于另一个。数据处理器可能会发现&#34;&#34;或查询功能,但这不是他们的主要功能。您发现在DataMappers中使用复杂的查询逻辑的次数越多,您就越想开始考虑将查询逻辑解耦到存储库中,同时让DataMappers为其主函数服务,将域对象映射到数据库,反之亦然。