В чем разница между шаблонами DAO и Repository?

424

В чем разница между объектами доступа к данным (DAO) и шаблонами репозитория? Я занимаюсь разработкой приложения с использованием Enterprise Java Beans (EJB3), Hibernate ORM в качестве инфраструктуры и доменно-управляемого проектирования (DDD) и тест-ориентированной разработки (TDD) в качестве методов проектирования.

Thurein
источник

Ответы:

472

DAOэто абстракция постоянства данных .
Repositoryэто абстракция коллекции объектов .

DAOбудет рассматриваться ближе к базе данных, часто на основе таблицы.
Repositoryбудет рассматриваться ближе к домену, имея дело только с совокупными корнями.

Repositoryможет быть реализовано с помощью DAOs, но вы бы не сделали обратное.

Кроме того, как Repositoryправило, более узкий интерфейс. Это должно быть просто набор объектов, с Get(id), Find(ISpecification), Add(Entity).

Подобный метод Updateподходит для a DAO, но не для a Repository- при использовании a Repositoryизменения сущностей обычно отслеживаются отдельным UnitOfWork.

Кажется распространенным видеть реализации, называемые a, Repositoryкоторые на самом деле более a DAO, и, следовательно, я думаю, что существует некоторая путаница в разнице между ними.

Квентин-starin
источник
27
Ну, вы бы не хотели, чтобы ваш класс DAO буквально реализовывал ваш IRepositoryинтерфейс. Вы бы хотели, чтобы ваш репозиторий использовал DAO в своей реализации. Помните, что DAO будет объектом для каждой таблицы, в то время как репозиторий почти всегда должен будет использовать несколько DAO для создания одного объекта. Если вы обнаружите, что это не тот случай, когда вашему репозиторию и сущности требуется доступ только к одной таблице, то вы, скорее всего, создаете анемичный домен.
Квентин Старин
29
Я заметил, что в мире .NET именно термин «репозиторий» используется для обозначения того, что по сути является DAO; «DAO» - это скорее Java-термин.
Уэйн Молина
14
@ Thurein DAO-s не для таблиц, шаблон только абстрагирует доступ к вашим данным - вы можете реализовать это так, как вам нравится (для таблицы, для группы или моделей). Рекомендуемый способ состоит в том, чтобы всегда формировать свои DAO на основе модели вашего домена, а не принимать во внимание постоянное основополагающее значение, поскольку это облегчает / делает его более понятным и дает вам немного больше гибкости в том, как вы сохраняете его (например, представьте, что вам нужно DAO, который хранит ваши данные в файлах XML или получает их из очереди сообщений, а не из базы данных ...).
Stef
21
@ Стеф, я не согласен. DAO возвращает данные по самому определению ( объект доступа к данным ). Репозиторий по определению возвращает доменные объекты. Следует признать, что хранилище будет использовать DAO, а не наоборот, потому что в ООП мы создаем доменные объекты из одного или нескольких объектов данных, а не наоборот.
Михай Данила
6
Почему репозиторий является концепцией «Только чтение», а DAO - «Чтение и запись»?
Деннис
121

Хорошо, думаю, я могу лучше объяснить, что я положил в комментариях :). Таким образом, в принципе, вы можете видеть оба этих варианта одинаково, хотя 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 немного более гибкий / универсальный, в то время как репозиторий немного более конкретен и ограничивает только тип.

Stef
источник
Если я правильно понял, например, у меня есть что-то подобное CarDescription, например, в language_idкачестве внешнего ключа, - тогда, чтобы узнать, что я должен сделать что-то вроде этого: CarRepository.getAll(new Criteria(carOwner.id, language.id));что даст мне все машины языка на определенном языке - это правильный способ сделать это ?
отображаемое имя
@StefanFalk, взгляните на Spring Data, он позволяет вам делать намного приятнее, чем это. например, это может быть написано так, CarRepository.findByLanguageId(language.id)и вам даже не нужно будет писать код, вы просто определяете интерфейс с помощью метода с таким именем, а Spring Data позаботится о создании для вас реализации класса по умолчанию. Довольно аккуратные вещи;)
Стеф
2
Прелесть Spring Data в том, что вам на самом деле не нужно писать запросы, вы просто создаете интерфейс (как тот TodoRepository в вашем примере, у которого есть метод findById). И вы практически сделали. Затем Spring Data находит все созданные вами интерфейсы, расширяющие интерфейс Repository, и создает для вас классы. Вы никогда не увидите эти классы и не сможете создавать новые экземпляры, но вам это не нужно, поскольку вы можете просто подключить интерфейс автоматически и позволить Spring найти этот объект репозитория.
Стеф
1
Наконец, вам не нужно использовать Spring Data, вы можете пойти по старому пути написания методов запросов самостоятельно (используя Criteria API и т. Д.), Но вы просто усложните свою жизнь ... Вы можете сказать, что у вас будет больше гибкости, но это не так, как если бы вы действительно хотели сходить с ума с вашими запросами, Spring Data позволяет вам сделать это двумя способами: аннотацией @Query, или, если это не сработает, вы можете создайте пользовательские репозитории, которые являются расширением, которое дает вам те же возможности, что и при написании собственной реализации с нуля.
Стеф
2
«Агрегированный корень» - это термин, часто связанный с шаблоном хранилища. Я не знаю, как бы вы использовали это в своем определении хранилища.
Кристиан Штремпфер
90

Шаблоны 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. Основной момент в шаблоне репозитория заключается в том, что с точки зрения клиента / пользователя он должен выглядеть или вести себя как коллекция. Что значит вести себя как коллекция, так это то, что ее не нужно создавать как экземпляр Collection collection = new SomeCollection(). Вместо этого это означает, что он должен поддерживать такие операции, как добавление, удаление, содержание и т. Д. Это суть шаблона репозитория.

На практике, например, в случае использования Hibernate, шаблон репозитория реализуется с помощью DAO. То есть экземпляр DAL может быть одновременно экземпляром шаблона DAO и шаблона репозитория.

Шаблон репозитория не обязательно является чем-то, что строится поверх DAO (как некоторые могут предположить). Если DAO спроектированы с интерфейсом, который поддерживает вышеупомянутые операции, то это экземпляр шаблона репозитория. Подумайте об этом: если DAO уже предоставляют набор операций, подобный коллекции, тогда зачем нужен дополнительный слой поверх него?

Назар Мерза
источник
5
«Если DAO уже предоставляют набор операций, подобный коллекции, тогда зачем нужен дополнительный слой поверх него?» Предположим, вы моделируете зоомагазин, и у вас есть таблица «PetType» с различными животными и их атрибутами (имя: «Кошка», тип: «Млекопитающее» и т. Д.), На которую ссылается таблица «Домашнее животное» из конкретных домашних животных, которых вы есть в магазине (название: "Китнисс", порода "Калико" и др.). Если вы хотите добавить животное типа, которого еще нет в базе данных, вы можете использовать репозиторий для группировки двух отдельных вызовов DAO (один для создания PetType, а другой для Pet) в одном методе, избегая связывания в DAOs
Matt
1
Превосходное объяснение, сэр!
Пол-Себастьян Маноле
74

Честно говоря, это выглядит как семантическое различие, а не техническое различие. Фраза «Объект доступа к данным» вообще не относится к «базе данных». И, хотя вы могли бы спроектировать его так, чтобы он был ориентирован на базу данных, я думаю, что большинство людей подумали бы сделать это как недостаток дизайна.

Цель DAO - скрыть детали реализации механизма доступа к данным. Чем отличается шаблон репозитория? Насколько я могу сказать, это не так. Сказать, что репозиторий отличается от DAO, потому что вы имеете дело с / возвращаете коллекцию объектов, не может быть правильным; DAO также могут возвращать коллекции объектов.

Все, что я читал о шаблоне репозитория, похоже, опирается на это различие: плохой дизайн DAO против хорошего дизайна DAO (он же шаблон проектирования репозитория).

rakehell404
источник
5
да, полностью согласен, они по существу одинаковы. DAO звучит в большей степени связанным с БД, но это не так. Как и в репозитории, это просто абстракция, используемая для скрытия того, где и как расположены данные.
Stef
+1 За это утверждение. Честно говоря, это выглядит как семантическое различие, а не техническое различие. Фраза «Объект доступа к данным» вообще не относится к «базе данных».
Судхакар Чавали
1
Смысл сравнения репозиториев и коллекций заключается не в том, что они обрабатывают / возвращают коллекции объектов, а в том, что репозитории ведут себя так, как будто они сами являются коллекциями. Например, в Java это означает, что в репозитории нет метода обновления, потому что при изменении объекта в коллекции он автоматически обновляется (поскольку в коллекциях Java хранятся только ссылки на объекты).
Кристоф Беме
17

Репозиторий - это более абстрактный термин, ориентированный на домен, который является частью 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

Мохамед Абед
источник
6

Основное отличие состоит в том, что репозиторий обрабатывает доступ к корням агрегата в агрегате, а DAO - к объектам. Поэтому обычно репозиторий делегирует фактическое постоянство совокупных корней DAO. Кроме того, поскольку совокупный корень должен обрабатывать доступ других объектов, ему может потребоваться делегировать этот доступ другим DAO.

pablochacin
источник
5

DAO предоставляет абстракцию для файлов базы данных / данных или любого другого механизма персистентности, чтобы можно было манипулировать уровнем персистентности, не зная деталей его реализации.

Принимая во внимание, что в классах репозитория несколько классов DAO могут использоваться внутри одного метода репозитория для выполнения операции с «точки зрения приложения». Таким образом, вместо использования нескольких DAO на уровне домена, используйте репозиторий, чтобы сделать это. Репозиторий - это уровень, который может содержать некоторую логику приложения, например: если данные доступны в кеше в памяти, тогда извлекайте их из кеша, в противном случае извлекайте данные из сети и сохраняйте их в кеше в памяти для последующего извлечения.

Рахул Растоги
источник
3

Репозиторий - это не что иное, как хорошо разработанный DAO.

ORM ориентированы на таблицы, но не DAO.

Нет необходимости использовать несколько DAO в репозитории, поскольку сам DAO может делать то же самое с репозиториями / сущностями ORM или любым поставщиком DAL, независимо от того, где и как машина сохраняется 1 таблица, 2 таблицы, n таблиц, половина таблицы, веб-сервис, таблица, веб-сервис и т. д. Сервисы используют несколько DAO / репозиториев.

Мой собственный DAO, скажем, CarDao имеет дело только с Car DTO, я имею в виду только Car DTO на входе и только возврат DTO автомобиля или наборы DTO автомобиля на выходе.

Так что, как и Repository, DAO на самом деле является IoC для бизнес-логики, позволяющей не запугивать интерфейсы сохраняемости стратегиями привязанности или наследием. DAO как инкапсулирует стратегию персистентности, так и обеспечивает интерфейс персистентности, связанный с доменом. Репозиторий - это просто другое слово для тех, кто не понял, что такое четко определенный DAO.

Сирил
источник
Прежде всего "ORM репозитории / сущности"? Вы имеете в виду организации ORM. Там нет такого понятия, как хранилище ORM. Во-вторых, ORM обычно имеют дело только с сущностями, т.е. доменные модели. DAO имеют дело с таблицами напрямую и абстрактным доступом к данным. Они также возвращают сущности. Хранилища являются высшей абстракцией, предлагая интерфейс для сбора сущностей. DAO может быть хранилищем, т.е. абстрагирование фактического механизма хранения, предоставление интерфейса к нему, а также представление представления объектов (кэша). DAO может использовать ORM для взаимодействия с базой данных и делегирования операций объекта.
Пол-Себастьян Маноле
3
Согласитесь с @brokenthorn. Наиболее важный момент в его комментарии: «Репозитории - это высшая абстракция», и эта абстракция становится необходимостью, когда вы хотите защитить код своего домена от технологии баз данных. Концепции драйвера ORM / Adapter / DB имеют тенденцию просачиваться в DAO. Если у вас есть приложение, которое поддерживает более одной технологии баз данных, или если вы хотите, чтобы ваше приложение не было заблокировано для базы данных, использование DAO непосредственно из модели домена не допускается.
Субхаш Бхушан
2

Попытайтесь выяснить, подходит ли 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

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

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

javaDisciple
источник
0

в очень простом предложении: существенным отличием является то, что репозитории представляют коллекции, в то время как DAO располагаются ближе к базе данных, часто гораздо более ориентированные на таблицы.

Алиреза Рахмани Халили
источник
DAO также может представлять коллекции / объекты ...
Юша Aleayoub
0

В рамках Spring есть аннотация, называемая репозиторием, а в описании этой аннотации есть полезная информация о репозитории, которая, я думаю, будет полезна для этого обсуждения.

Указывает, что аннотированный класс представляет собой «Репозиторий», первоначально определенный Domain-Driven Design (Evans, 2003) как «механизм для инкапсуляции хранения, извлечения и поиска, который эмулирует коллекцию объектов».

Команды, реализующие традиционные шаблоны Java EE, такие как «Объект доступа к данным», могут также применять этот стереотип к классам DAO, хотя следует позаботиться о том, чтобы понять различие между объектом доступа к данным и репозиториями в стиле DDD, прежде чем делать это. Эта аннотация является стереотипом общего назначения, и отдельные команды могут сузить свою семантику и использовать по мере необходимости.

Аннотированный таким образом класс подходит для трансляции Spring DataAccessException при использовании вместе с PersistenceExceptionTranslationPostProcessor. Аннотированный класс также разъясняется в отношении его роли в общей архитектуре приложения с целью инструментария, аспектов и т. Д.

Али еганех
источник