数据映射器(Data Mapper)和仓储(Repository)之间到底有什么区别?

50

我一直在尝试找出数据映射器和仓库之间的区别,但到目前为止还没有找到。似乎专业程序员说“仓库是另一个抽象层,位于映射层之上,其中查询构造代码集中”。这听起来可理解,但仍然有些抽象。我以前在stackoverflow上读过这篇文章,但它只让我更加困惑: 数据映射器模式与仓库模式有何不同?

我想我需要的是简单的解释和具体/实际的例子,说明这两种模式的区别,以及仓库做了什么,数据映射器不做的事情,反之亦然。你们中是否有人知道一个很好的例子来说明数据映射器和仓库的概念?最好是相同的例子,一个使用数据映射器,另一个使用仓库。谢谢,我将非常感激。我现在还很困惑...

2个回答

55
假设您的应用程序管理具有名称、年龄和职务属性的“Person”对象实例。您希望将这些对象持久化、从持久化介质中检索它们,以及可能更新(例如在生日时增加年龄)或删除它们。这些任务通常称为 CRUD,即创建 Create、读取 Read、更新 Update 和删除 Delete。
最好将业务逻辑与处理“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"

另一种持久层可以是文件系统,或者是选择在两个表 (PersonAgePersonJobTitle) 中存储 Person 对象的另一种数据库格式。

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

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

  • 业务逻辑需要读取或持久化对象时,会处理 Repository,而不关心其如何实现。
  • Repository 处理 DataMapper,以便在特定的持久性介质中读写对象。
  • 对于查询,Repository 依赖于由 DataMapper 提供的模式 (例如,jobTitle 的值可以在 PersonTable 表中的 JobTitle 列中找到),但不依赖于任何映射器的实现。
  • 对于数据库持久性,DataMapper 依赖于一个 DB 层,该层屏蔽了它与 Oracle/Sybase/MSSQL/OtherProvider 的细节。

这些模式并没有“不同”,它们只是展示了不同的基本特征。


2
我明白了,感谢您的解释。我认为Repository是业务对象(模型)和数据访问对象(DataMapper)之间的抽象层,这种解释合理吗? - Lord Yggdrasill
+1 我花了几个小时来理解这些概念,试图获得一个整体的视野来设计我的模型层... 但是你清晰简洁的回答让一切变得如此清晰。谢谢! - user4932891
3
数据映射器与数据库交互,但并不一定具有复杂的查询功能。而仓储库则暴露/实现更高级别的查询功能。 - G-Wiz

51

我知道我的回答有点晚,但它可能会帮助将来遇到同样问题并发现可用的答案不完全回答问题的人(当我第一次看到这个问题时,我也有同感)。

在阅读了《企业应用架构模式》(Martin Fowler)之后,我也很难区分数据映射器和存储库之间的区别。

这就是我发现的这两个概念的最终核心:

  • 存储库 的作用类似于领域对象的集合,具有强大的查询功能(Evans,DDD)
  • 数据映射器 “在对象和数据库之间移动数据,同时使它们彼此独立以及与映射器本身独立”(Fowler,《企业应用架构模式》)

存储库 是一个通用的概念,不一定必须将任何内容存储到数据库中,其主要功能是提供领域对象的集合式(启用查询)访问(无论这些对象是否来自数据库都无关紧要)。存储库本身可能(而且通常会)包含数据映射器。

数据映射器 是领域对象和数据库之间的中间层,允许它们独立演进,而不会有一个依赖于另一个。数据映射器可能具有“查找”或查询功能,但这并不是它们的主要功能。当您发现自己在数据映射器中使用了复杂的查询逻辑时,就越想开始考虑将该查询逻辑解耦成存储库,同时让您的数据映射器继续服务于其主要功能,即将领域对象映射到数据库中以及反之亦然。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接