DAO和存储库模式之间的区别是什么?

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

220079 次浏览

DAO数据持久性的抽象 Repository是对对象的集合的抽象

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

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

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

Update这样的方法适用于DAO,但不适用于Repository——当使用Repository时,对实体的更改通常会由单独的UnitOfWork跟踪。

很常见的是,被称为Repository的实现实际上更像是DAO,因此我认为它们之间存在一些混淆。

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

查看这些链接:

< a href = " http://warren.mayocchi.com/2006/07/27/repository-or-dao/ " > http://warren.mayocchi.com/2006/07/27/repository-or-dao/ # EYZ0 < / p >

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

如果有兴趣,也可以参考以下链接:

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

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

< a href = " http://devlicio.us/blogs/casey/archive/2009/02/20/ddd-the-repository-pattern。aspx " rel = " http://devlicio.us/blogs/casey/archive/2009/02/20/ddd-the-repository-pattern.aspx nofollow”> < / >

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

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

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

DAO的目的是隐藏数据访问机制的实现细节。存储库模式有何不同?据我所知,不是这样的。对于DAO来说,因为处理/返回对象集合而说存储库是不同的是不对的;dao还可以返回对象的集合。

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

关键的区别在于存储库处理对聚合根的访问,而DAO处理对实体的访问。因此,存储库通常将聚合根的实际持久性委托给DAO。此外,由于聚合根必须处理其他实体的访问,那么它可能需要将这种访问委托给其他dao。

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

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

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

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

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

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

在实践中,例如在使用Hibernate的情况下,Repository模式是用DAO实现的。也就是说,一个DAL实例可以同时是DAO模式和Repository模式的实例。

存储库模式不一定是在DAO之上构建的(有些人可能会这样建议)。如果dao被设计为支持上述操作的接口,那么它就是Repository模式的实例。想想看,如果dao已经提供了一组类似于集合的操作,那么为什么还需要在上面再加一个层呢?

好吧,我想我可以更好地解释我在评论中写的东西:)。 因此,基本上,您可以看到两者是相同的,尽管DAO是一种比Repository更灵活的模式。如果您想同时使用这两种方法,那么您应该在dao中使用Repository。我将在下面解释每一个:

存储库:

它是一个特定类型对象的存储库-它允许你搜索特定类型的对象以及存储它们。通常它只处理一种类型的对象。例如,AppleRepository将允许您执行AppleRepository.findAll(criteria)AppleRepository.save(juicyApple)。 注意,存储库使用的是域模型术语(不是DB术语——与数据如何在任何地方持久化无关)

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

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

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

例如,你可以很容易地使用UserDao来公开类似的方法

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

所有这些都与User(和安全性)相关,并且可以在同一个DAO下指定。对于Repository则不是这样。

最后

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

存储库不过是设计良好的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实际上是什么的人来说,存储库只是另一个词

在一个非常简单的句子中:显著的差异是 存储库代表集合,而dao更接近数据库,通常更接近 table-centric。< / p >

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

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

提供了一种更简单的方式从存储中获取数据,隐藏了丑陋的查询。

存储库也处理数据,隐藏查询和所有这些,但是,存储库处理< >强业务/域对象< / >强

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

例如,a# EYZ0可以包含一些类似-的方法

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

存储库可以包含一些类似-的方法

   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;
}
}
}
}

这个教程帮助我很容易地理解主要概念。

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

它可以只是一个访问数据的接口,在这种情况下,数据可以从DB/Cache甚至REST(现在不太常见,因为我们可以很容易地在各自的REST /IPC客户端中分离它们)访问。

这种方法中的回购可以由任何ORM解决方案实现,如果底层缓存/回购发生变化,它不会被传播/影响服务/业务层。

dao可以接受/返回域类型。考虑一个学生域,关联的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
      

   

}


}