DAO 和 Repository 模式有什么区别?

发布于 12-21 18:42 字数 136 浏览 5 评论 0 原文

数据访问对象 (DAO) 和存储库模式之间有什么区别?我正在开发一个应用程序,使用 Enterprise Java Beans (EJB3)、Hibernate ORM 作为基础架构,并使用领域驱动设计 (DDD) 和测试驱动开发 (TDD) 作为设计技术。

What is the difference between Data Access Objects (DAO) and Repository patterns? I am developing an application using Enterprise Java Beans (EJB3), Hibernate ORM as infrastructure, and Domain-Driven Design (DDD) and Test-Driven Development (TDD) as design techniques.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

内心激荡 2024-12-28 18:42:18

DAO数据持久化的抽象。
存储库对象集合的抽象。

DAO 将被认为更接近数据库,通常以表为中心。
Repository 将被认为更接近域,仅处理聚合根。

Repository 可以使用 DAO 来实现,但你不会做相反的事情。

此外,Repository 通常是一个较窄的接口。它应该只是一个对象集合,带有 Get(id)Find(ISpecification)Add(Entity)

Update 这样的方法适用于 DAO,但不适用于 Repository - 当使用 Repository 时,更改为实体通常由单独的工作单元来跟踪。

被称为Repository的实现似乎很常见,它实际上更像是一个DAO,因此我认为人们对它们之间的区别存在一些困惑。

DAO is an abstraction of data persistence.
Repository is an abstraction of a collection of objects.

DAO would be considered closer to the database, often table-centric.
Repository would be considered closer to the Domain, dealing only in Aggregate Roots.

Repository could be implemented using DAO's, but you wouldn't do the opposite.

Also, a Repository is generally a narrower interface. It should be simply a collection of objects, with a Get(id), Find(ISpecification), Add(Entity).

A method like Update is appropriate on a DAO, but not a Repository - when using a Repository, changes to entities would usually be tracked by separate UnitOfWork.

It does seem common to see implementations called a Repository that is really more of a DAO, and hence I think there is some confusion about the difference between them.

心在旅行 2024-12-28 18:42:18

好吧,我想我可以更好地解释我在评论中添加的内容:)。
因此,基本上,您可以将它们视为相同的,尽管 DAO 是比存储库更灵活的模式。如果您想同时使用两者,则可以使用 DAO 中的存储库。我将在下面逐一解释:

存储库:

它是特定类型对象的存储库 - 它允许您搜索特定类型的对象并存储它们。通常它只会处理一种类型的对象。例如,AppleRepository 允许您执行AppleRepository.findAll(criteria)AppleRepository.save(juicyApple)
请注意,存储库使用的是域模型术语(而不是数据库术语 - 与数据如何在任何地方保存无关)。

存储库很可能将所有数据存储在同一个表中,而模式并不要求这样做。事实上,它只处理一种类型的数据,这使得它在逻辑上连接到一个主表(如果用于数据库持久性)。

DAO - 数据访问对象(换句话说 - 用于访问数据的对象)

DAO 是一个为您定位数据的类(它主要是一个查找器,但通常也用于存储数据)。该模式不限制您存储相同类型的数据,因此您可以轻松拥有一个定位/存储相关对象的 DAO。

例如,您可以轻松地让 UserDao 公开类似的方法,

Collection<Permission> findPermissionsForUser(String userId)
User findUser(String userId)
Collection<User> findUsersForPermission(Permission permission)

所有这些方法都与用户(和安全性)相关,并且可以在相同的 DAO 下指定。存储库的情况并非如此。

最后

请注意,这两种模式实际上意味着相同(它们存储数据并抽象对数据的访问,并且它们的表达都更接近域模型并且几乎不包含任何数据库引用),但它们的使用方式可能略有不同,DAO更加灵活/通用,而存储库更加具体并且仅限于类型。

OK, think I can explain better what I've put in comments :).
So, basically, you can see both those as the same, though DAO is a more flexible pattern than Repository. If you want to use both, you would use the Repository in your DAO-s. I'll explain each of them below:

REPOSITORY:

It's a repository of a specific type of objects - it allows you to search for a specific type of objects as well as store them. Usually it will ONLY handle one type of objects. E.g. AppleRepository would allow you to do AppleRepository.findAll(criteria) or AppleRepository.save(juicyApple).
Note that the Repository is using Domain Model terms (not DB terms - nothing related to how data is persisted anywhere).

A repository will most likely store all data in the same table, whereas the pattern doesn't require that. The fact that it only handles one type of data though, makes it logically connected to one main table (if used for DB persistence).

DAO - data access object (in other words - object used to access data)

A DAO is a class that locates data for you (it is mostly a finder, but it's commonly used to also store the data). The pattern doesn't restrict you to store data of the same type, thus you can easily have a DAO that locates/stores related objects.

E.g. you can easily have UserDao that exposes methods like

Collection<Permission> findPermissionsForUser(String userId)
User findUser(String userId)
Collection<User> findUsersForPermission(Permission permission)

All those are related to User (and security) and can be specified under then same DAO. This is not the case for Repository.

Finally

Note that both patterns really mean the same (they store data and they abstract the access to it and they are both expressed closer to the domain model and hardly contain any DB reference), but the way they are used can be slightly different, DAO being a bit more flexible/generic, while Repository is a bit more specific and restrictive to a type only.

じее 2024-12-28 18:42:18

DAO 和存储库模式是实现数据访问层 (DAL) 的方法。那么,我们首先从 DAL 开始。

访问数据库的面向对象应用程序必须具有一些逻辑来处理数据库访问。为了保持代码的整洁和模块化,建议将数据库访问逻辑隔离到单独的模块中。在分层架构中,这个模块就是DAL。

到目前为止,我们还没有讨论任何具体的实现:只是将数据库访问逻辑放在单独的模块中的一般原则。

现在,我们如何实施这个原则呢?嗯,一种已知的实现方法,特别是使用 Hibernate 这样的框架,就是 DAO 模式。

DAO 模式是一种生成 DAL 的方式,通常每个域实体都有自己的 DAO。例如,UserUserDaoAppointmentAppointmentDao 等。使用 Hibernate 的 DAO 示例:http://gochev.blogspot.ca/2009/08/hibernate-generic-dao.html

那么什么是Repository模式呢?与DAO一样,Repository模式也是实现DAL的一种方式。存储库模式的要点是,从客户端/用户的角度来看,它应该看起来或表现得像一个集合。表现得像集合的意思并不是说它必须像 Collection collection = new SomeCollection() 那样实例化。相反,它意味着它应该支持添加、删除、包含等操作。这就是存储库模式的本质。

在实践中,例如在使用Hibernate的情况下,Repository模式是通过DAO来实现的。也就是说,DAL 的实例可以同时是 DAO 模式和存储库模式的实例。

存储库模式不一定是建立在 DAO 之上的东西(正如某些人可能建议的那样)。如果 DAO 设计有支持上述操作的接口,那么它就是 Repository 模式的一个实例。想想看,如果 DAO 已经提供了一组类似集合的操作,那么在它之上还需要额外的一层吗?

DAO and Repository pattern are ways of implementing Data Access Layer (DAL). So, let's start with DAL, first.

Object-oriented applications that access a database, must have some logic to handle database access. In order to keep the code clean and modular, it is recommended that database access logic should be isolated into a separate module. In layered architecture, this module is DAL.

So far, we haven't talked about any particular implementation: only a general principle that putting database access logic in a separate module.

Now, how we can implement this principle? Well, one know way of implementing this, in particular with frameworks like Hibernate, is the DAO pattern.

DAO pattern is a way of generating DAL, where typically, each domain entity has its own DAO. For example, User and UserDao, Appointment and AppointmentDao, etc. An example of DAO with Hibernate: http://gochev.blogspot.ca/2009/08/hibernate-generic-dao.html.

Then what is Repository pattern? Like DAO, Repository pattern is also a way achieving DAL. The main point in Repository pattern is that, from the client/user perspective, it should look or behave as a collection. What is meant by behaving like a collection is not that it has to be instantiated like Collection collection = new SomeCollection(). Instead, it means that it should support operations such as add, remove, contains, etc. This is the essence of Repository pattern.

In practice, for example in the case of using Hibernate, Repository pattern is realized with DAO. That is an instance of DAL can be both at the same an instance of DAO pattern and Repository pattern.

Repository pattern is not necessarily something that one builds on top of DAO (as some may suggest). If DAOs are designed with an interface that supports the above-mentioned operations, then it is an instance of Repository pattern. Think about it, If DAOs already provide a collection-like set of operations, then what is the need for an extra layer on top of it?

娇纵 2024-12-28 18:42:18

坦率地说,这看起来像是语义上的区别,而不是技术上的区别。短语“数据访问对象”根本不是指“数据库”。而且,尽管您可以将其设计为以数据库为中心,但我认为大多数人会认为这样做是一个设计缺陷。

DAO 的目的是隐藏数据访问机制的实现细节。存储库模式有何不同?据我所知,事实并非如此。说存储库与 DAO 不同是因为您正在处理/返回对象的集合,这是不正确的; DAO 还可以返回对象的集合。

我读到的有关存储库模式的所有内容似乎都依赖于这种区别:糟糕的 DAO 设计与良好的 DAO 设计(又名存储库设计模式)。

Frankly, this looks like a semantic distinction, not a technical distinction. The phrase Data Access Object doesn't refer to a "database" at all. And, although you could design it to be database-centric, I think most people would consider doing so a design flaw.

The purpose of the DAO is to hide the implementation details of the data access mechanism. How is the Repository pattern different? As far as I can tell, it isn't. Saying a Repository is different to a DAO because you're dealing with/return a collection of objects can't be right; DAOs can also return collections of objects.

Everything I've read about the repository pattern seems rely on this distinction: bad DAO design vs good DAO design (aka repository design pattern).

紙鸢 2024-12-28 18:42:18

存储库是更抽象的面向领域的术语,是领域驱动设计的一部分,它是领域设计和通用语言的一部分,DAO 是数据访问技术的技术抽象,存储库只关心管理现有数据和工厂以创建数据。

检查这些链接:

Repository is more abstract domain oriented term that is part of Domain Driven Design, it is part of your domain design and a common language, DAO is a technical abstraction for data access technology, repository is concerns only with managing existing data and factories for creation of data.

Check these links:

成熟稳重的好男人 2024-12-28 18:42:18

DAO 允许以更简单的方式从存储中获取数据,隐藏丑陋的查询。

存储库也处理数据并隐藏查询等,但是存储库处理业务/域对象

存储库将使用 DAO 从存储中获取数据,并使用该数据来恢复业务对象

例如,DAO 可以包含一些类似的方法 -

 public abstract class MangoDAO{
   abstract List<Mango>> getAllMangoes();
   abstract Mango getMangoByID(long mangoID);
}

并且 Repository 可以包含一些类似的方法 -

   public abstract class MangoRepository{
       MangoDao mangoDao = new MangDao;

       Mango getExportQualityMango(){

       for(Mango mango:mangoDao.getAllMangoes()){
        /*Here some business logics are being applied.*/
        if(mango.isSkinFresh()&&mangoIsLarge(){
           mango.setDetails("It is an export quality mango");
            return mango;
           }
       }
    }
}

教程帮助我轻松掌握主要概念。

A DAO allows for a simpler way to get data from storage, hiding the ugly queries.

Repository deals with data too and hides queries and all that but, a repository deals with business/domain objects.

A repository will use a DAO to get the data from the storage and uses that data to restore a business object.

For example, A DAO can contain some methods like that -

 public abstract class MangoDAO{
   abstract List<Mango>> getAllMangoes();
   abstract Mango getMangoByID(long mangoID);
}

And a Repository can contain some method like that -

   public abstract class MangoRepository{
       MangoDao mangoDao = new MangDao;

       Mango getExportQualityMango(){

       for(Mango mango:mangoDao.getAllMangoes()){
        /*Here some business logics are being applied.*/
        if(mango.isSkinFresh()&&mangoIsLarge(){
           mango.setDetails("It is an export quality mango");
            return mango;
           }
       }
    }
}

This tutorial helped me to get the main concept easily.

小苏打饼 2024-12-28 18:42:18

关键区别在于存储库处理对聚合中聚合根的访问,而 DAO 处理对实体的访问。因此,存储库将聚合根的实际持久性委托给 DAO 是很常见的。此外,由于聚合根必须处理其他实体的访问,因此它可能需要将此访问权限委托给其他 DAO。

The key difference is that a repository handles the access to the aggregate roots in a an aggregate, while DAO handles the access to entities. Therefore, it's common that a repository delegates the actual persistence of the aggregate roots to a DAO. Additionally, as the aggregate root must handle the access of the other entities, then it may need to delegate this access to other DAOs.

终止放荡 2024-12-28 18:42:18

存储库只不过是精心设计的 DAO。

ORM 以表为中心,但不是以 DAO 为中心。

无需在存储库中使用多个 DAO,因为 DAO 本身可以对 ORM 存储库/实体或任何 DAL 提供程序执行完全相同的操作,无论汽车在何处以及如何持久保存 1 个表、2 个表、n 个表、半个表、一个Web 服务、表格和 Web 服务等。
服务使用多个 DAO/存储库。

我自己的DAO,假设CarDao只处理Car DTO,我的意思是,只在输入中接受Car DTO,并且在输出中只返回car DTO或car DTO集合。

所以就像Repository一样,DAO实际上是一个IoC,对于业务逻辑来说,允许持久化接口不会被持久化策略或遗留问题吓倒。
DAO 既封装了持久化策略,又提供了与域相关的持久化接口。
对于那些不了解定义明确的 DAO 实际上是什么的人来说,存储库只是另一个词。

Repository are nothing but well-designed DAO.

ORM are table centric but not DAO.

There's no need to use several DAO in repository since DAO itself can do exactly the same with ORM repositories/entities or any DAL provider, no matter where and how a car is persisted 1 table, 2 tables, n tables, half a table, a web service, a table and a web service etc.
Services uses several DAO/repositories.

My own DAO, let's say CarDao only deal with Car DTO,I mean, only take Car DTO in input and only return car DTO or car DTO collections in output.

So just like Repository, DAO actually is an IoC, for the business logic, allowing persitence interfaces not be be intimidated by persitence strategies or legacies.
DAO both encapsulates the persistence strategy and does provide the domaine-related persitence interface.
Repository is just an another word for those who had not understood what a well-defined DAO actualy was.

Hello爱情风 2024-12-28 18:42:18

DAO 提供了对数据库/数据文件或任何其他持久性机制的抽象,以便可以在不知道其实现细节的情况下操作持久层。

而在 Repository 类中,可以在单个 Repository 方法中使用多个 DAO 类,以从“应用程序角度”完成操作。因此,不要在域层使用多个 DAO,而是使用存储库来完成它。
存储库是一个可能包含一些应用程序逻辑的层,例如:如果内存缓存中有数据,则从缓存中获取数据,否则,从网络获取数据并将其存储在内存缓存中以供下次使用检索。

DAO provides abstraction on database/data files or any other persistence mechanism so that, persistence layer could be manipulated without knowing its implementation details.

Whereas in Repository classes, multiple DAO classes can be used inside a single Repository method to get an operation done from "app perspective". So, instead of using multiple DAO at Domain layer, use repository to get it done.
Repository is a layer which may contain some application logic like: If data is available in in-memory cache then fetch it from cache otherwise, fetch data from network and store it in in-memory cache for next time retrieval.

尝蛊 2024-12-28 18:42:18

尝试找出 DAO 或 Repository 模式是否最适用于以下情况:
想象一下,您希望为各种类型的数据源(例如 RDBMS、LDAP、OODB、XML 存储库和平面文件)的持久机制提供统一的数据访问 API。

如果有兴趣,另请参阅以下链接:

http://www.codeinsanity .com/2008/08/repository-pattern.html

http://blog.fedecarg.com/2009/03/ 15/领域驱动设计存储库/

http://devlicio.us/blogs/casey /archive/2009/02/20/ddd-the-repository-pattern.aspx

http://en.wikipedia.org/wiki/Domain-driven_design

"="">http://msdn.microsoft.com/en-us/magazine/dd419654.aspx

Try to find out if DAO or the Repository pattern is most applicable to the following situation :
Imagine you would like to provide a uniform data access API for a persistent mechanism to various types of data sources such as RDBMS, LDAP, OODB, XML repositories and flat files.

Also refer to the following links as well, if interested:

http://www.codeinsanity.com/2008/08/repository-pattern.html

http://blog.fedecarg.com/2009/03/15/domain-driven-design-the-repository/

http://devlicio.us/blogs/casey/archive/2009/02/20/ddd-the-repository-pattern.aspx

http://en.wikipedia.org/wiki/Domain-driven_design

http://msdn.microsoft.com/en-us/magazine/dd419654.aspx

溇涏 2024-12-28 18:42:18

根据 Spring 文档 没有明显的区别:

@Repository 注释是任何满足以下条件的类的标记
存储库的角色或构造型(也称为数据访问对象
或 DAO)。

Per Spring documentation there is no clear difference:

The @Repository annotation is a marker for any class that fulfills the
role or stereotype of a repository (also known as Data Access Object
or DAO).

巡山小妖精 2024-12-28 18:42:18

如果我们考虑两种设计模式的原始定义 DAO存储库看起来非常相似。主要区别在于字典及其来源(Oracle 与 Fowler)。

引用:

  • DAO - “将数据资源的客户端接口与其数据访问机制分开”和“DAO 实现使用数据源所需的访问机制。数据源可以是持久存储(如 RDBMS)、外部服务(如 B2B 交换)、存储库(如 LDAP 数据库)或通过 CORBA Internet ORB 间协议 (IIOP) 或低级访问的业务服务套接字。”

  • 存储库 - “使用类似集合的接口来访问域对象,在域和数据映射层之间进行中介。” “从概念上讲,存储库封装了数据存储中持久保存的一组对象以及对它们执行的操作,提供了持久层的更加面向对象的视图。存储库还支持实现干净分离和单向依赖的目标域和数据映射层之间。”

根据这些引文,这两种设计模式都调解领域层和数据层之间的通信。此外,Repository 与 ORM 相关,相反,DAO 是一个更通用的接口,用于从任何地方访问数据。

If we consider the original definitions of both design patterns DAO and Repository appear very similar. The main difference is the dictionary and the source from which they came (Oracle vs. Fowler).

Quote:

  • DAO - "separates a data resource's client interface from its data access mechanisms" and "The DAO implements the access mechanism required to work with the data source. The data source could be a persistent store like an RDBMS, an external service like a B2B exchange, a repository like an LDAP database, or a business service accessed via CORBA Internet Inter-ORB Protocol (IIOP) or low-level sockets."

  • Repository - "Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects." and "Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers."

Based on these citations, both design patterns mediate communication between the domain layer and the data layer. Moreover, Repository is associated with ORM and on the contrary DAO is a more generic interface for accessing data from anywhere.

離殇 2024-12-28 18:42:18

DAO 可能并不总是与 Only DataBase 显式相关,

它可能只是一个访问数据的接口,这种情况下的数据可以从 DB/Cache 甚至 REST 访问(现在不太常见,因为我们可以轻松地将它们分开相应的 Rest/IPC 客户端),

此方法中的 Repo 可以由任何 ORM 解决方案实现,如果底层缓存/Repo 发生更改,它将不会传播/影响服务/业务层。

DAO 可以接受/返回域类型。对于 Student Domain,关联的 DAO 类将是 StudentDao

StudentDao {

    StudentRepository, 
    StudentCache, 

    Optional<Student> getStudent(Id){

       // Use StudentRepository/StudentCache to Talk to DD & Cache 
       // Cache Type can be the same as Domain Type, DB Type(Entities) should be a Same/Different Type.
   
    }

    Student updateStudent(Student){

       // Use StudentRepository/StudentCache to Talk to DD & Cache 
       // Cache Type can be the same as Domain Type, DB Type(Entities) should be a Same/Different Type.
   
    }

}

DAO 可以接受/返回子域类型。考虑一个学生域,它有子域,比如出勤/主题,它将有一个 DAO 类 StudentDao,

StudentDao {

    StudentRepository, SubjectRepository, AttendanceRepository
    StudentCache, SubjectCache, AttendanceCache

    Set<Subject> getStudentSubject(Id){

       // Use SubjectRepository/SubjectCache to Talk to DD & Cache 
       
    }

    Student addNewSubjectToStudent(ID, Subject){

       // Use SubjectRepository/SubjectCache to Talk to DD & Cache 
      
   
    }

}

DAOs might not always explicitly be related to Only DataBase,

It can be just an Interface to access Data, Data in this context might be accessed from DB/Cache or even REST (not so common these days, Since we can easily separate them in their respective Rest/IPC Clients),

Repo here in this approach be implemented by any of the ORM Solutions, If the underlying Cache/Repo Changes it'll not be propagated/impacts Service/Business Layers.

DAOs can accept/return Domain Types. Consider for a Student Domain, the associated DAO class will be StudentDao

StudentDao {

    StudentRepository, 
    StudentCache, 

    Optional<Student> getStudent(Id){

       // Use StudentRepository/StudentCache to Talk to DD & Cache 
       // Cache Type can be the same as Domain Type, DB Type(Entities) should be a Same/Different Type.
   
    }

    Student updateStudent(Student){

       // Use StudentRepository/StudentCache to Talk to DD & Cache 
       // Cache Type can be the same as Domain Type, DB Type(Entities) should be a Same/Different Type.
   
    }

}

DAOs can accept/return SubDomain Types. Consider a Student Domain, that has Sub Domain, say Attendance / Subject that will have a DAO class StudentDao,

StudentDao {

    StudentRepository, SubjectRepository, AttendanceRepository
    StudentCache, SubjectCache, AttendanceCache

    Set<Subject> getStudentSubject(Id){

       // Use SubjectRepository/SubjectCache to Talk to DD & Cache 
       
    }

    Student addNewSubjectToStudent(ID, Subject){

       // Use SubjectRepository/SubjectCache to Talk to DD & Cache 
      
   
    }

}
清晨说晚安 2024-12-28 18:42:18

DAO 和存储库

DAO 模式和存储库模式都是将业务逻辑与数据持久逻辑分离的模式。他们
通常可以互换使用,这可能会导致混淆,但它们之间存在明显的差异。

DAO

DAO 模式要求为单个对象创建用于简单 CRUD 操作的抽象(因此称为数据访问对象)
一种。一种类型可以由具有自己的 DAO 的其他类型组成,因此 DAO 可以使用其他类型
DAO 但通常不会使用存储库。
DAO 被用作聚合根 - 通过它的主要实体
与对象集群的所有交互都应该发生,它还负责检查所有不变量和
聚合的规则,以确保聚合始终保持有效状态。

存储库

存储库模式要求创建用于 CRUD 操作的抽象(使用其他 DAO)、监听、
对一种类型的对象集合进行搜索、与聚合验证无关的附加数据访问/业务逻辑等。
存储库可以使用 DAO 或其他存储库。

DAO and Repository

DAO pattern and Repository pattern are both patterns for separation of business logic from data persistence logic. They
are often used interchangeable which may lead to confusion, but there are distinct differences.

DAO

DAO pattern calls for creating an abstraction used for simple CRUD operations (hence Data Access Object) for a single object of
one type. The one type can be composed of other types with their own DAO's, thus a DAO may use other
DAO's but will typically never use a Repository.
DAO's are used as an Aggregate Root - the main entity through which
all interactions with the cluster of objects should occur, it is also responsible for checking all invariants and
rules for the aggregate to ensure the aggregate always remains in a valid state.

Repository

Repository pattern calls for creating an abstraction used for CRUD operations (using other DAO's), listening,
searching, additional data access/business logic not related to the aggregate validation, etc. on a collection of objects of one type.
A Repository may use DAO's or other Repositories.

绅刃 2024-12-28 18:42:18

用一个非常简单的句子来说:显着的区别是
存储库代表集合,而 DAO 更接近数据库,通常更接近数据库
以表为中心。

in a very simple sentence: The significant difference being
that Repositories represent collections, whilst DAOs are closer to the database, often being far more
table-centric.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文