数据访问对象(DAO)和仓储库模式有何区别?我正在使用企业Java Beans(EJB3)、Hibernate ORM基础设施以及领域驱动设计(DDD)和测试驱动开发(TDD)作为设计技术开发应用程序。
数据访问对象(DAO)和仓储库模式有何区别?我正在使用企业Java Beans(EJB3)、Hibernate ORM基础设施以及领域驱动设计(DDD)和测试驱动开发(TDD)作为设计技术开发应用程序。
DAO
是数据持久化的抽象。
Repository
是一组对象的抽象。
DAO
与数据库更接近,通常以表为中心。
Repository
更接近领域,仅处理聚合根。
Repository
可以使用DAO
实现,但反之则不行。
此外,Repository
通常是较窄的接口。它应该只是一个对象集合,并提供Get(id)
、Find(ISpecification)
和Add(Entity)
方法。
Update
方法适用于DAO
,而不适用于Repository
- 使用Repository
时,对实体的更改通常由单独的UnitOfWork跟踪。
似乎常见的实现被称为Repository
,但实际上更像是DAO
,因此我认为存在一些关于它们之间区别的困惑。
IRepository
接口。您希望您的存储库在其实现中使用DAO。请记住,DAO将是每个表对象,而存储库几乎总是需要使用多个DAO来构建单个实体。如果您发现不是这种情况,即您的存储库和实体仅需要访问单个表,则最有可能正在构建贫血的域模型。 - quentin-starin好的,我觉得我可以更好地解释我在评论中提到的内容:基本上,你可以把它们两个看作是一样的,虽然DAO是比Repository更灵活的一种模式。如果你想同时使用它们两个,你将在你的DAO中使用Repository。我将对它们各自进行解释:
它是一个特定类型对象的存储库——它允许您搜索特定类型的对象以及存储它们。通常情况下,它只会处理一种类型的对象。例如,AppleRepository
将允许您执行 AppleRepository.findAll(criteria)
或者 AppleRepository.save(juicyApple)
。
请注意,Repository 使用的是领域模型术语(而不是数据库术语——与数据如何持久化无关)。
存储库很可能会将所有数据存储在同一个表中,但该模式并不要求如此。然而,它仅处理一种类型的数据,这使它逻辑上连接到一个主表(如果用于数据库持久性)。
DAO 是一个为您定位数据的类(主要是查找器,但通常也用于存储数据)。这种模式不限制你存储相同类型的数据,因此你可以很容易地拥有一个定位/存储相关对象的 DAO。
例如,您可以很容易地拥有一个 UserDao,该 UserDao 公开类似于:
Collection<Permission> findPermissionsForUser(String userId)
User findUser(String userId)
Collection<User> findUsersForPermission(Permission permission)
所有这些都与用户(和安全)有关,可以在同一个DAO中指定。这对于Repository来说并非如此。
请注意,这两种模式实际上意思相同(它们存储数据并抽象出对数据的访问,并且它们都更接近领域模型并且几乎不包含任何数据库引用),但它们的使用方式可能略有不同,DAO更加灵活/通用,而Repository则更具特定性和限制性,只适用于某一类型。
CarRepository.findByLanguageId(language.id)
,而且你甚至不需要编写代码,只需定义一个具有该名称方法的接口,Spring Data会为您构建默认类实现。相当不错的东西 ;) - StefTodoReporitory
,然后实现那些方法,比如MyRepository extends TodoRepository
,其中MyRepository
使用Hibernate进行持久化。网络上有太多的信息,我正在一个已经有较大数据库和服务器/客户端通信的项目中开始感到困惑。 - Stefan FalkfindById
的方法)。然后你就几乎完成了。Spring Data 会查找所有这些你已经创建的扩展 Repository 接口的接口,并为你创建类。你永远看不到这些类,也无法创建新实例,但你不需要这样做,因为你可以自动装配接口并让 Spring 定位那个仓库对象。 - StefCollection collection = new SomeCollection()
仓库(Repository)是领域驱动设计中更加抽象的面向领域的术语,是领域设计和共同语言的一部分,而DAO是数据访问技术的技术抽象。Repository 仅关注于管理现有数据和用于创建数据的工厂。
请查看以下链接:
http://warren.mayocchi.com/2006/07/27/repository-or-dao/ http://fabiomaulo.blogspot.com/2009/09/repository-or-dao-repository.html
一个DAO可以让从存储中获取数据变得更加简单,同时隐藏了丑陋的查询语句。
仓库(Repository)也处理数据并隐藏查询,但是它处理的是业务/领域对象。
仓库将使用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;
}
}
}
}
这个教程帮助我轻松理解了主要概念。
DAO提供了对数据库/数据文件或任何其他持久性机制的抽象,以便可以在不知道其实现细节的情况下操作持久层。
而在Repository类中,可以在单个Repository方法中使用多个DAO类来从“应用程序角度”完成操作。因此,不要在域层使用多个DAO,而是使用repository来完成操作。 Repository是一个层,可能包含一些应用逻辑,例如:如果数据可用于内存缓存,则从缓存中获取它;否则,从网络中获取数据并将其存储在内存缓存中以供下次检索。
仓库就是经过精心设计的 DAO。
ORM 是以表为中心,而不是 DAO。
在仓库中不需要使用多个 DAO,因为 DAO 本身可以与 ORM 仓库 / 实体或任何数据访问层提供程序执行完全相同的操作,不管汽车存储在哪里以及如何存储(1张表、2张表、n张表、半个表、Web 服务、一张表和一个 Web 服务等)。服务使用多个 DAO/仓库。
我的自己的 DAO,假设叫做 CarDao,只处理 Car DTO,我的意思是,只接受 Car DTO 作为输入,并且只返回 Car DTO 或 Car DTO 集合作为输出。
所以,就像仓库一样,DAO 实际上是业务逻辑的 IoC,允许持久化接口不被持久化策略或传统所威胁。DAO 既封装了持久化策略,也提供了与领域相关的持久化接口。仓库只是那些没有理解精确定义的 DAO 的人们用来指代 DAO 的另一个词。
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