我一直在努力找出数据映射器和存储库之间的区别,但到目前为止我还没有。在我看来,专家程序员说“存储库是查询构造代码集中的映射层的另一个抽象层”。这似乎可以理解,但仍然有点抽象。我之前在stackoverflow上读过这篇文章,它让我更加困惑: How is the Data Mapper pattern different from the Repository Pattern?
我想我需要的是关于两种模式如何不同的简单解释和具体/实际示例,以及存储库对数据映射器不起作用的内容,反之亦然。你们中的任何人都知道一个关于说明数据映射器和存储库概念的好例子吗?如果它是相同的示例,只有一个使用数据映射器而另一个使用存储库会更好。谢谢,我非常感谢。到目前为止我仍然很困惑......
答案 0 :(得分:17)
假设您的应用管理Person
个对象,每个实例都有name
,age
和jobTitle
属性。
您希望保留此类对象,然后从持久性介质中检索并更新(例如,在他们的生日,增加日期)或删除。这些任务通常称为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"
。
另一个持久层可以是文件系统,也可以是另一种选择在Person
和PersonAge
两个表中存储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)之后,我也无法识别数据映射器和存储库之间的区别。
我发现这两个概念最终归结为:
存储库是一个通用概念,不一定要将任何东西存储到数据库中,其主要功能是提供对域对象的集合(支持查询)访问(无论它们是否存在)从数据库得到的除了点之外)。存储库可能(通常会)包含DataMappers本身。
DataMappers 充当域对象和数据库之间的中间层,允许它们独立发展而不依赖于另一个。数据处理器可能会发现&#34;&#34;或查询功能,但这不是他们的主要功能。您发现在DataMappers中使用复杂的查询逻辑的次数越多,您就越想开始考虑将查询逻辑解耦到存储库中,同时让DataMappers为其主函数服务,将域对象映射到数据库,反之亦然。