数据访问对象(DAO)和存储库模式之间的区别是什么?我正在开发一个应用程序,使用企业Java bean (EJB3), Hibernate ORM作为基础设施,领域驱动设计(DDD)和测试驱动开发(TDD)作为设计技术。
当前回答
如果我们考虑设计模式DAO和Repository的原始定义,就会发现它们非常相似。主要的区别是字典和它们的来源(Oracle vs. Fowler)。
引用:
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."
基于这些引用,这两种设计模式都调解了领域层和数据层之间的通信。此外,Repository与ORM相关联,而DAO则是用于从任何地方访问数据的更通用的接口。
其他回答
坦率地说,这看起来像是语义上的区别,而不是技术上的区别。短语数据访问对象根本不是指“数据库”。而且,尽管您可以将其设计为以数据库为中心,但我认为大多数人会认为这样做是一种设计缺陷。
DAO的目的是隐藏数据访问机制的实现细节。存储库模式有何不同?据我所知,不是这样的。说一个存储库与一个DAO不同,因为你在处理/返回一个对象的集合,这是不对的;dao还可以返回对象的集合。
我所读到的关于存储库模式的所有内容似乎都依赖于这样的区别:坏的DAO设计与好的DAO设计(又名存储库设计模式)。
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;
}
}
}
}
这个教程帮助我很容易地理解了主要概念。
DAO是数据持久性的抽象。 存储库是对象集合的抽象。
DAO被认为更接近数据库,通常以表为中心。 存储库将被认为更接近域,只处理聚合根。
存储库可以使用DAO来实现,但您不会做相反的事情。
另外,Repository通常是一个更窄的接口。它应该是一个简单的对象集合,包含Get(id)、Find(isspec)、Add(Entity)。
像Update这样的方法适用于DAO,但不适用于Repository——当使用Repository时,对实体的更改通常由单独的UnitOfWork跟踪。
被称为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可能并不总是显式地与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
}
}
推荐文章
- Hibernate中不同的保存方法之间有什么区别?
- 有人能解释一下JPA和Hibernate中的mappedBy吗?
- 什么是领域驱动设计?
- 使Hibernate忽略未映射的实例变量
- javax.transaction.Transactional vs . org.springframework.transaction.annotation.Transactional
- buildSessionFactory()配置方法在Hibernate中已弃用?
- 存储库和服务层的区别?
- DDD -实体不能直接访问存储库的规则
- JPA orphanRemoval=true如何不同于ON DELETE CASCADE DML子句
- 如何映射一个组合键与JPA和Hibernate?
- 如何使用旧版本的Hibernate(~2009)来计算行数?
- 我如何使JPA OneToOne关系变懒
- 混淆:@NotNull vs. @Column(nullable = false)与JPA和Hibernate
- Hibernate的第一级和第二级缓存是什么?
- Hibernate抛出org.hibernate.AnnotationException:没有为entity指定标识符:com..domain.idea.MAE_MFEView