数据访问对象(DAO)和存储库模式之间有什么区别?我正在开发一个使用Enterprise Java Beans(EJB3),Hibernate ORM作为基础架构,域驱动设计(DDD)和测试驱动开发(TDD)作为设计技术的应用程序。
答案 0 :(得分:384)
DAO
是数据持久性的抽象
Repository
是对象集合的抽象。
DAO
将被视为更接近数据库,通常以表格为中心
Repository
将被视为更接近域,仅处理聚合根。
Repository
可以使用DAO
来实现,但你不会做相反的事情。
此外,Repository
通常是较窄的界面。它应该只是一个对象集合,具有Get(id)
,Find(ISpecification)
,Add(Entity)
。
Update
等方法适用于DAO
,但不适用于Repository
- 使用Repository
时,实体的更改通常会由单独的UnitOfWork跟踪。
看到Repository
的实现更像是DAO
似乎很常见,因此我认为它们之间存在一些混淆。
答案 1 :(得分:98)
好的,我想我可以更好地解释我在评论中提出的内容:)。 所以,基本上,你可以看到两者相同,尽管DAO比Repository更灵活。如果要同时使用两者,则可以在DAO-s中使用存储库。我将在下面解释每一个:
它是特定类型对象的存储库 - 它允许您搜索特定类型的对象以及存储它们。通常它只能处理一种类型的对象。例如。 AppleRepository
允许您AppleRepository.findAll(criteria)
或AppleRepository.save(juicyApple)
。
请注意,存储库使用的是域模型术语(不是数据库术语 - 与数据在任何地方的持久性无关)。
存储库很可能将所有数据存储在同一个表中,而模式不需要这样。事实上,它只处理一种类型的数据,使其逻辑上连接到一个主表(如果用于数据库持久性)。
DAO是一个为您定位数据的类(它主要是一个查找器,但它通常也用于存储数据)。该模式不会限制您存储相同类型的数据,因此您可以轻松地使用DAO来定位/存储相关对象。
E.g。你可以很容易地让UserDao公开像
这样的方法Collection<Permission> findPermissionsForUser(String userId)
User findUser(String userId)
Collection<User> findUsersForPermission(Permission permission)
所有这些都与用户(和安全性)相关,并且可以在相同的DAO下指定。这不是Repository的情况。
请注意,两种模式的确意味着相同(它们存储数据并抽象访问它们,并且它们都表示更接近域模型,几乎不包含任何数据库引用),但它们的使用方式可能略有不同,DAO更灵活/通用,而Repository对某种类型更具体和限制。
答案 2 :(得分:72)
DAO和Repository模式是实现数据访问层(DAL)的方法。所以,让我们先从DAL开始。
访问数据库的面向对象的应用程序必须具有一些处理数据库访问的逻辑。为了保持代码清洁和模块化,建议将数据库访问逻辑隔离到单独的模块中。在分层架构中,此模块是DAL。
到目前为止,我们还没有谈到任何特定的实现:只是将数据库访问逻辑放在一个单独的模块中的一般原则。
现在,我们如何实施这一原则?好吧,有人知道实现这个的方法,特别是像Hibernate这样的框架,就是DAO模式。
DAO模式是一种生成DAL的方式,通常,每个域实体都有自己的DAO。例如,User
和UserDao
,Appointment
和AppointmentDao
等。带有Hibernate的DAO示例:http://gochev.blogspot.ca/2009/08/hibernate-generic-dao.html。
那么什么是存储库模式?像DAO一样,Repository模式也是实现DAL的一种方式。 Repository模式的要点是,从客户端/用户的角度来看,它应该看起来或表现为集合。行为像集合的含义并不是必须像Collection collection = new SomeCollection()
那样实例化。相反,它意味着它应该支持诸如add,remove,contains等操作。这是Repository模式的本质。
实际上,例如在使用Hibernate的情况下,Repository模式是用DAO实现的。这是DAL的一个实例可以同时是DAO模式和Repository模式的实例。
存储库模式不一定是建立在DAO之上的东西(正如某些人所暗示的那样)。如果DAO设计有支持上述操作的接口,则它是Repository模式的实例。想一想,如果DAO已经提供了类似集合的操作集,那么在它之上需要一个额外的层呢?
答案 3 :(得分:60)
DAO的目的是隐藏数据访问机制的实现细节。存储库模式有何不同?据我所知,事实并非如此。说存储库与DAO的不同因为你正在处理/返回一个对象的集合是不对的; DAO还可以返回对象集合。
我所读到的关于存储库模式的所有内容似乎都依赖于这种区别:糟糕的DAO设计与良好的DAO设计(也就是存储库设计模式)。
答案 4 :(得分:16)
存储库是更抽象的面向领域的术语,是域驱动设计的一部分,它是域设计和通用语言的一部分,DAO是数据访问技术的技术抽象,存储库仅涉及管理现有数据和工厂用于创建数据。
检查以下链接:
http://warren.mayocchi.com/2006/07/27/repository-or-dao/ http://fabiomaulo.blogspot.com/2009/09/repository-or-dao-repository.html
答案 5 :(得分:6)
关键区别在于存储库处理对聚合中聚合根的访问,而DAO处理对实体的访问。因此,存储库通常会将聚合根的实际持久性委托给DAO。此外,由于聚合根必须处理其他实体的访问,因此可能需要将此访问权委托给其他DAO。
答案 6 :(得分:3)
存储库只不过是精心设计的DAO。
ORM以表格为中心但不是DAO。
不需要在存储库中使用多个DAO,因为DAO本身可以与ORM存储库/实体或任何DAL提供程序完全相同,无论汽车在何处以及如何持久存在1个表,2个表,n个表,半个表,Web服务,表和Web服务等。 服务使用几个DAO /存储库。
我自己的DAO,让我们说CarDao只与Car DTO打交道,我的意思是,只接受Car DTO的输入,只返回汽车DTO或车载DTO系列。
所以就像Repository一样,DAO实际上是一个IoC,用于业务逻辑,允许persitence接口不被persitence策略或遗产吓倒。 DAO既封装了持久性策略,又提供了与域有关的persitence接口。 对于那些不了解定义明确的DAO的人来说,存储库只是另一个词。
答案 7 :(得分:2)
尝试找出DAO或Repository模式是否最适用于以下情况: 想象一下,您希望为各种类型的数据源(如RDBMS,LDAP,OODB,XML存储库和平面文件)提供持久机制的统一数据访问API。
如果感兴趣,也可以参考以下链接:
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
答案 8 :(得分:1)
在spring框架中,有一个称为存储库的注释,在此注释的描述中,有关于存储库的有用信息,我认为这对本次讨论很有用。
指示带注释的类最初是“存储库” 由域驱动设计(Evans,2003)定义为“一种 封装模拟以下内容的存储,检索和搜索行为 对象集合”。
实施传统Java EE模式的团队,例如“数据访问 对象”也可以将这种构造型应用于DAO类, 应该理解数据访问之间的区别 在执行此操作之前,请使用对象和DDD样式的存储库。该注释是 通用的刻板印象,各个团队可能会缩小他们的 语义和适当使用。
这样注释的类有资格使用Spring DataAccessException 与a结合使用时的翻译 PersistenceExceptionTranslationPostProcessor。带注释的类是 还阐明了其在整个应用程序体系结构中的作用 出于工具,方面等目的。
答案 9 :(得分:1)
DAO 提供了一种更简单的方法来从存储中获取数据,隐藏丑陋的查询。
存储库也处理数据并隐藏查询,但所有存储库都处理 业务/域对象 。
存储库将使用DAO从存储中获取数据,并使用该数据还原 业务对象 。
例如, DAO 可以包含类似的方法-
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;
}
}
}
}
这个tutorial帮助我轻松掌握了主要概念。
答案 10 :(得分:0)
用一个非常简单的句子: 存储库代表集合,而DAO则更接近数据库,而通常要远得多 以表格为中心。
答案 11 :(得分:0)
DAO提供了对数据库/数据文件或任何其他持久性机制的抽象,因此可以在不知道其实现细节的情况下操纵持久层。
在存储库类中,可以在单个存储库方法中使用多个DAO类,以从应用程序角度完成操作。因此,不要在域层使用多个DAO,而要使用存储库来完成它。 存储库是一个可能包含某些应用逻辑的层,例如:如果数据在内存高速缓存中可用,则从高速缓存中获取数据,否则,从网络获取数据并将其下次存储在内存高速缓存中检索。