【问题标题】:What exactly is the difference between a data mapper and a repository?数据映射器和存储库之间到底有什么区别?
【发布时间】:2015-03-15 18:36:55
【问题描述】:

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

我想我需要的是关于这两种模式有何不同的简单解释和具体/实际示例,以及存储库做什么数据映射器不做什么,反之亦然。你们中有人知道说明数据映射器和存储库概念的好例子吗?如果它是同一个例子会更好,只有一个使用数据映射器,另一个使用存储库。谢谢,我将非常感谢。到现在我还是很迷茫……

【问题讨论】:

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


    【解决方案1】:

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

    您想持久化这些对象,从持久化介质中检索它们,并可能更新(例如,在它们的生日,增加年龄)或删除。这些任务通常被称为 CRUD,来自 Create、Read、Update 和 Delete。

    最好将您的“业务”逻辑与处理Person 对象持久性的逻辑分离。这允许您在不影响业务逻辑的情况下更改持久性逻辑(例如,从 DB 到分布式文件系统)。

    您可以通过将所有持久性逻辑封装在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") 转换为持久层可以理解的内容。

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

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

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

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

    • 业务逻辑在想要读取或持久化对象时处理Repository,而不关心它是如何实现的
    • Repository 处理DataMapper 在特定持久性介质中读取/写入对象时。
    • 对于查询,Repository 依赖于由DataMapper 提供的模式(例如,jobTitle 值在PersonTable 表的JobTitle 列中找到)但不依赖于任何实现 的映射器。
    • 对于 DB 持久性,DataMapper 依赖于一个 DB 层,它可以保护它免受 Oracle/Sybase/MSSQL/OtherProvider 详细信息的影响。

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

    【讨论】:

    • 我明白了,谢谢你的解释。我认为 Repository 是业务对象(Model)和数据访问对象(DataMapper)之间的抽象层,这是一种合理的解释方式吗?
    • +1 我花了好几个小时在这些概念上思考,试图获得一个设计模型层的整体愿景......你的清晰而简单的答案突然变得如此清晰。谢谢!
    • 数据映射器与数据库交互,但不一定具有复杂的查询能力。存储库公开/实现更高级别的查询功能。
    【解决方案2】:

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

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

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

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

    Repositories 是一个通用概念,不一定要将任何东西存储到数据库中,它的主要功能是提供对域对象(无论是否被获取)的类集合(启用查询)访问来自数据库是除此之外的重点)。存储库可能(并且通常会)包含 DataMapper 本身。

    DataMappers 充当域对象和数据库之间的中间层,允许它们独立发展而没有任何一个依赖于另一个。 Datamappers 可能具有“查找”或查询功能,但这并不是它们的主要功能。您发现在 DataMappers 中使用精细查询逻辑的次数越多,您就越想开始考虑将查询逻辑解耦到存储库中,同时让 DataMappers 服务于它们的主要功能,将域对象映射到数据库,反之亦然。

    【讨论】:

      猜你喜欢
      • 2017-05-18
      • 2015-09-15
      • 1970-01-01
      • 1970-01-01
      • 2016-08-12
      • 2013-12-28
      • 1970-01-01
      • 1970-01-01
      • 2016-02-27
      相关资源
      最近更新 更多