В чем разница между шаблонами DAO и Repository?
В чем разница между объектами доступа к данным (DAO) и шаблонами репозитория? Я занимаюсь разработкой приложения с использованием Enterprise Java Beans (EJB3), Hibernate ORM в качестве инфраструктуры и доменно-управляемого проектирования (DDD) и тест-ориентированной разработки (TDD) в качестве методов проектирования.
15 ответов
DAO - это абстракция постоянства данных. Репозиторий - это абстракция коллекции объектов.
DAO будет считаться ближе к базе данных, часто ориентированной на таблицы. Хранилище будет считаться ближе к домену, имея дело только с совокупными корнями. Репозиторий может быть реализован с использованием DAO, но вы бы не сделали обратное.
Кроме того, репозиторий, как правило, более узкий интерфейс. Это должна быть просто коллекция объектов, с Get(id)
, Find(ISpecification)
, Add(Entity)
, Метод как Update
подходит для DAO, но не для репозитория - при использовании репозитория изменения в сущностях обычно отслеживаются отдельным UnitOfWork.
Кажется распространенным видеть реализации, называемые репозиторием, которые на самом деле являются скорее DAO, и, следовательно, я думаю, что существует некоторая путаница в разнице между ними.
Хорошо, думаю, я могу лучше объяснить, что я положил в комментариях:). Таким образом, в принципе, вы можете видеть оба этих варианта одинаково, хотя DAO- более гибкий шаблон, чем Repository. Если вы хотите использовать оба, вы должны использовать репозиторий в ваших 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 немного более гибкий / универсальный, в то время как репозиторий немного более конкретен и ограничивает только тип.
Шаблоны DAO и Repository представляют собой способы реализации уровня доступа к данным (DAL). Итак, сначала начнем с DAL.
Объектно-ориентированные приложения, которые обращаются к базе данных, должны иметь некоторую логику для обработки доступа к базе данных. Чтобы сохранить код чистым и модульным, рекомендуется, чтобы логика доступа к базе данных была изолирована в отдельный модуль. В многоуровневой архитектуре этот модуль является DAL.
До сих пор мы не говорили о какой-либо конкретной реализации: только общий принцип, заключающийся в размещении логики доступа к базе данных в отдельном модуле.
Теперь, как мы можем реализовать этот принцип? Хорошо, один из известных способов реализации этого, в частности с помощью таких сред, как Hibernate, - это шаблон DAO.
Шаблон DAO - это способ генерации DAL, где обычно каждый объект домена имеет свой собственный DAO. Например, User
а также UserDao
, Appointment
а также AppointmentDao
и т. д. Пример DAO с Hibernate: http://gochev.blogspot.ca/2009/08/hibernate-generic-dao.html.
Тогда что такое шаблон репозитория? Как и DAO, шаблон репозитория также является способом достижения DAL. Суть шаблона Repository заключается в том, что с точки зрения клиента / пользователя он должен выглядеть или вести себя как коллекция. Под поведением коллекции подразумевается не то, что ее нужно создавать как Collection collection = new SomeCollection()
, Вместо этого это означает, что он должен поддерживать такие операции, как добавление, удаление, содержание и т. Д. Это суть шаблона репозитория.
На практике, например, в случае использования Hibernate, шаблон репозитория реализуется с помощью DAO. То есть экземпляр DAL может быть одновременно экземпляром шаблона DAO и шаблоном репозитория.
Шаблон репозитория не обязательно является чем-то, что строится поверх DAO (как некоторые могут предположить). Если DAO спроектированы с интерфейсом, который поддерживает вышеупомянутые операции, то это экземпляр шаблона репозитория. Подумайте об этом: если DAO уже предоставляют набор операций, подобный коллекции, тогда зачем нужен дополнительный слой поверх него?
Честно говоря, это выглядит как семантическое различие, а не техническое различие. Фраза "Объект доступа к данным" вообще не относится к "базе данных". И, хотя вы могли бы спроектировать его так, чтобы он был ориентирован на базу данных, я думаю, что большинство людей подумали бы сделать это как недостаток дизайна.
Цель DAO - скрыть детали реализации механизма доступа к данным. Чем отличается шаблон репозитория? Насколько я могу сказать, это не так. Говорить, что репозиторий отличается от DAO, потому что вы имеете дело с / возвращаете коллекцию объектов, не может быть правильным; DAO также могут возвращать коллекции объектов.
Все, что я читал о шаблоне репозитория, похоже, опирается на это различие: плохой дизайн DAO против хорошего дизайна DAO (он же шаблон проектирования репозитория).
Репозиторий - это более абстрактный термин, ориентированный на домен, который является частью Domain Driven Design, он является частью дизайна вашего домена и общим языком, DAO - это техническая абстракция для технологии доступа к данным, репозиторий касается только управления существующими данными и фабриками для создания данные.
проверьте эти ссылки:
http://warren.mayocchi.com/2006/07/27/repository-or-dao/ http://fabiomaulo.blogspot.com/2009/09/repository-or-dao-repository.html
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.
DAO предоставляет абстракцию для файлов базы данных / данных или любого другого механизма персистентности, так что уровень персистентности можно манипулировать, не зная деталей его реализации.
Принимая во внимание, что в классах репозитория несколько классов DAO могут использоваться в одном методе репозитория для выполнения операции с точки зрения приложения. Таким образом, вместо использования нескольких DAO на уровне домена, используйте репозиторий, чтобы сделать это. Репозиторий - это слой, который может содержать некоторую логику приложения, например: если данные доступны в кеше в памяти, то извлекайте их из кеша, в противном случае извлекайте данные из сети и сохраняйте их в кеше в памяти для последующего извлечения.
Репозиторий - это не что иное, как хорошо разработанный DAO.
ORM ориентированы на таблицы, но не DAO.
Нет необходимости использовать несколько DAO в репозитории, так как сам DAO может делать то же самое с репозиториями / сущностями ORM или любым поставщиком DAL, независимо от того, где и как машина сохраняется 1 таблица, 2 таблицы, n таблиц, половина таблицы, веб-сервис, таблица, веб-сервис и т. д. Сервисы используют несколько DAO / репозиториев.
Мой собственный DAO, скажем, CarDao имеет дело только с Car DTO, я имею в виду только Car DTO на входе и только возврат DTO или наборов DTO автомобилей на выходе.
Так что, как и Repository, DAO на самом деле является IoC для бизнес-логики, позволяющей не запугивать интерфейсы сохраняемости стратегиями привязанности или наследием. DAO как инкапсулирует стратегию персистентности, так и обеспечивает интерфейс персистентности, связанный с доменом. Репозиторий - это просто другое слово для тех, кто не понял, что такое четко определенный DAO.
Попытайтесь выяснить, подходит ли DAO или шаблон репозитория к следующей ситуации: представьте, что вы хотели бы предоставить единый API доступа к данным для постоянного механизма для различных типов источников данных, таких как RDBMS, LDAP, OODB, репозитории XML и плоские файлы.
Также, если интересно, обратитесь к следующим ссылкам:
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
В документации Spring нет четкой разницы:
Аннотация @Repository — это маркер для любого класса, который выполняет роль или стереотип репозитория (также известный как объект доступа к данным или DAO).
Если мы рассмотрим исходные определения обоих шаблонов проектирования, DAO и репозиторий кажутся очень похожими. Основное отличие заключается в словаре и источнике, из которого они взяты (Oracle vs. Fowler).
Цитировать:
DAO — «отделяет клиентский интерфейс ресурса данных от его механизмов доступа к данным» и «DAO реализует механизм доступа, необходимый для работы с источником данных. Источником данных может быть постоянное хранилище, такое как СУБД, внешняя служба, такая как обмен B2B. , репозиторий, такой как база данных LDAP, или бизнес-служба, доступ к которой осуществляется через CORBA Internet Inter-ORB Protocol (IIOP) или низкоуровневые сокеты».
Репозиторий — «посредник между слоями отображения домена и данных, используя интерфейс, похожий на коллекцию, для доступа к объектам домена». и «Концептуально репозиторий инкапсулирует набор объектов, сохраняемых в хранилище данных, и операции, выполняемые над ними, обеспечивая более объектно-ориентированное представление уровня сохранения. Репозиторий также поддерживает цель достижения четкого разделения и односторонней зависимости. между слоями отображения домена и данных».
Основываясь на этих цитатах, оба шаблона проектирования опосредуют связь между уровнем предметной области и уровнем данных. Более того, репозиторий связан с ORM, а DAO, наоборот, является более общим интерфейсом для доступа к данным из любого места.
В фреймворке Spring есть аннотация, называемая репозиторием, и в описании этой аннотации есть полезная информация о репозитории, которая, я думаю, будет полезна для этого обсуждения.
Указывает, что аннотированный класс является "репозиторием", первоначально определенным Domain-Driven Design (Evans, 2003) как "механизм для инкапсуляции поведения при хранении, извлечении и поиске, который имитирует набор объектов".
Команды, реализующие традиционные шаблоны Java EE, такие как "объект доступа к данным", также могут применять этот стереотип к классам DAO, хотя перед этим следует понимать разницу между объектом доступа к данным и репозиториями в стиле DDD. Эта аннотация представляет собой стереотип общего назначения, и отдельные команды могут сузить свою семантику и использовать ее по мере необходимости.
Аннотированный таким образом класс имеет право на преобразование Spring DataAccessException при использовании вместе с PersistenceExceptionTranslationPostProcessor. Аннотированный класс также поясняется в отношении его роли в общей архитектуре приложения с точки зрения инструментов, аспектов и т. Д.
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
}
}
В очень простом предложении: существенным отличием является то, что репозитории представляют коллекции, в то время как DAO располагаются ближе к базе данных, часто гораздо более ориентированные на таблицы.