Чим відрізняються шаблони DAO від сховища?


423

Чим відрізняються шаблони об'єктів доступу до даних (DAO) та сховища? Я розробляю додаток, використовуючи Enterprise Java Beans (EJB3), Hibernate ORM як інфраструктуру та Design-Driven Design (DDD) та Test-Driven Development (TDD) як методи проектування.

Відповіді:


471

DAOє абстрагуванням збереження даних .
Repositoryце абстракція колекції предметів .

DAOбуде розглядатися ближче до бази даних, часто орієнтованої на таблицю.
Repositoryбуде розглядатися ближче до Домену, що має справу лише в агрегованих коренях.

Repositoryможе бути реалізований за допомогою DAO's, але ви не зробите навпаки.

Також, a, Repositoryяк правило, вужчий інтерфейс. Це повинно бути просто набір об'єктів, з Get(id), Find(ISpecification), Add(Entity).

Метод на зразок Updateпідходить для a DAO, але не a Repository- при використанні a Repository, зміни об'єктів зазвичай відслідковуються окремим UnitOfWork.

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


26
Ну, ви б не хотіли, щоб ваш клас DAO буквально реалізував ваш IRepositoryінтерфейс. Ви хочете, щоб ваш сховище використовував DAO у своїй реалізації. Пам'ятайте, що DAO буде об'єктом за столом, тоді як для сховища майже завжди доведеться використовувати кілька DAO для створення однієї сутності. Якщо ви виявите, що це не так, що вашому сховищу та об'єкту потрібно лише отримати доступ до однієї таблиці, ви, швидше за все, будуєте анемічний домен.
квентин-зірин

29
Я помітив у світі .NET, зокрема, термін "сховище" використовується для позначення того, що по суті є DAO; "DAO" - це більше термін Java.
Уейн Моліна

14
@Thurein DAO не мають таблиці, шаблон лише обмежує доступ до ваших даних - ви можете реалізовувати все, що завгодно (за таблицею, за групою чи моделями). Рекомендований спосіб - завжди формувати свої DAO на основі вашої моделі домену, а не враховувати основні наполегливості, тому що це полегшує / зрозуміліше у використанні та надає вам трохи більшої гнучкості в тому, як ви його зберігаєте (наприклад, уявіть, що вам потрібно DAO, який зберігає ваші дані у файлах XML або отримує їх із черги повідомлень, а не з бази даних ...).
Стеф

21
@Stef Я не згоден. DAO повертає дані за самим його визначенням (об'єкт доступу до даних ). Репозиторій за своїм визначенням повертає об’єкти домену. Слід обґрунтувати, що сховище використовуватиме DAO, а не навпаки, тому що в OOP ми складаємо доменні об’єкти з одного або декількох об'єктів даних, а не навпаки.
Mihai Danila

6
Чому репозиторій - це концепція "лише для читання", а DAO - "читання та запис"?
Денніс

120

Гаразд, думаю, я можу краще пояснити, що я виклав у коментарях :). Таким чином, в основному ви можете бачити обидва ці ж, хоча DAO є більш гнучким, ніж сховище. Якщо ви хочете використовувати обидва, ви б використали сховище у своїх 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 трохи більш гнучким / загальним, тоді як Репозиторій трохи більш специфічний і обмежує лише тип.


Якщо я маю на це право, наприклад, у мене є щось подібне CarDescription, наприклад, language_idяк зовнішній ключ - тоді я можу зробити щось подібне: CarRepository.getAll(new Criteria(carOwner.id, language.id));що дало б мені всі машини мовою певної мови - це правильний спосіб зробити це ?
displayname

@StefanFalk, погляньте на Spring Data, це дозволяє вам робити набагато приємніші дзвінки, ніж це. наприклад, це може бути написано як, CarRepository.findByLanguageId(language.id)і вам навіть не потрібно буде писати код, ви просто визначите інтерфейс методом з цим ім'ям, і Spring Data піклується про те, щоб створити для вас реалізацію класу за замовчуванням. Досить акуратні речі;)
Стеф

2
Краса Spring Data полягає в тому, що вам насправді не потрібно писати запити, ви просто створюєте інтерфейс (як, наприклад, TodoRepository у вашому прикладі, який має метод findById). І ви практично зробили. Тоді, що робить Spring Data, це те, що вони знаходять усі створені вами інтерфейси, які розширюють інтерфейс сховища та створюють для вас класи. Ви ніколи не побачите цих класів, і ви не зможете створювати нові екземпляри, але вам цього не потрібно, оскільки ви можете просто автонаправити інтерфейс і дозволити Spring знайти цей об’єкт сховища.
Стеф

1
Нарешті, вам не доведеться використовувати Spring Data, ви можете піти старим способом написання методів запиту самостійно (використовуючи API критеріїв тощо), але ви просто зробите своє життя трохи складнішим ... Ви можете сказати, що Ви б мали більше такої гнучкості, але це неправда, як ніби ви справді хочете з глузду зі своїми запитами. Spring Data дозволяє вам зробити два способи: анотація @Query, або якщо це не працює, ви можете створити власні сховища, які є розширенням, яке дає вам таку ж силу, як якщо ви пишете власну реалізацію з нуля.
Стеф

2
"Агрегований корінь" - термін, часто пов'язаний із шаблоном сховища. Я не знаю, як би ви використовували це зі своїм визначенням сховища.
Крістіан Стремпфер

90

Шаблон DAO та сховища - це способи реалізації рівня доступу до даних (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(). Натомість це означає, що він повинен підтримувати такі операції, як додавання, видалення, вміст тощо. Це суть шаблону репозиторію.

На практиці, наприклад, у випадку використання сплячого режиму, шаблон репозиторію реалізується за допомогою DAO. Це екземпляр DAL може бути одночасно і тим самим екземпляром шаблону DAO, і шаблоном сховища.

Шаблон сховища - це не обов'язково щось, що створюється на базі DAO (як деякі можуть запропонувати). Якщо DAO розроблені з інтерфейсом, який підтримує вищезазначені операції, то це екземпляр шаблону репозиторію. Подумайте над тим, якщо DAO вже надають збірний набір операцій, то яка потреба в додатковому шарі поверх нього?


5
"Якщо DAO вже надають збірний набір операцій, то яка потреба в додатковому шарі поверх нього?" Припустимо, ви моделюєте зоомагазин і у вас є таблиця "PetType" з різними тваринами та їх атрибутами (назва: "Кішка", тип: "Ссавці" тощо), на яку посилається таблиця "Домашня тварина" конкретних домашніх тварин, які ви мати в магазині (назва: «Катніс», порода: «Калико» та ін.). Якщо ви хочете додати тварину типу, яка ще не знаходиться в базі даних, ви можете використовувати сховище для групування двох окремих викликів DAO (один для створення PetType, а другий для Pet) одним методом, уникаючи сполучення в DAO
Matt

1
Чудове пояснення, сер!
Пол-Себастьян Маноле

74

Чесно кажучи, це виглядає як семантичне розрізнення, а не технічне розмежування. Фраза "Об'єкт доступу до даних" взагалі не посилається на "базу даних". І хоча ви могли б спроектувати його як орієнтованого на базу даних, я думаю, що більшість людей вважають за все це недолік дизайну.

Мета DAO - приховати деталі реалізації механізму доступу до даних. Чим відрізняється модель сховища? Наскільки я можу сказати, це не так. Скажіть, що сховище відрізняється від DAO, тому що ви маєте справу з поверненням колекції об'єктів і не може бути правильним; DAO також можуть повернути колекції об'єктів.

Все, що я читав про шаблон сховища, схоже, покладається на це розрізнення: поганий дизайн DAO проти хороший дизайн DAO (він же модель дизайну сховища).


5
так, повністю згоден, вони по суті однакові. DAO звучить більше відносно БД, але це не так. Як і сховище, це лише абстракція, що використовується для приховування місця та розміщення даних.
Стеф

+1 Для цього твердження. Чесно кажучи, це виглядає як семантичне розрізнення, а не технічне розмежування. Фраза "Об'єкт доступу до даних" взагалі не посилається на "базу даних".
Sudhakar Chavali

1
Точка при порівнянні Сховища і колекції не то, що вони мають справу / повернення колекції об'єктів, але Сховища поводяться так , як ніби вони є самі колекції. Наприклад, у Java це означає, що у сховищі немає методу оновлення, оскільки при зміні об'єкта в колекції він автоматично оновлюється (оскільки колекції Java зберігають лише посилання на об'єкти).
Крістоф Бьоме

17

Репозиторій - більш абстрактний доменно-орієнтований термін, який є частиною дизайну, керованого доменом, він є частиною дизайну вашого домену та загальною мовою, 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.


5

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

В той час, як у класах репозиторію, кілька класів DAO можуть використовуватися всередині одного методу репозиторію, щоб отримати операцію з "точки зору програми". Отже, замість того, щоб використовувати кілька DAO на рівні домену, використовуйте сховище, щоб зробити це. Репозиторій - це шар, який може містити таку логіку програми, як: Якщо дані доступні в кеш-пам'яті, тоді вийміть її з кешу в іншому випадку, вийміть дані з мережі та зберігайте їх у кеш-пам'яті для наступного пошуку.


3

Репозиторій - це не що інше, як добре розроблений DAO.

ОРМ є орієнтованими на таблицю, але не DAO.

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

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

Таким чином, як і сховище, DAO насправді є IoC, для бізнес-логіки, що дозволяє інтерфейсам стійкості не залякувати стратегіями переслідування або спадщиною. DAO і інкапсулює стратегію стійкості, і надає інтерфейс, пов'язаний з доменом. Сховище - це ще одне слово для тих, хто не розумів, що таке чітко визначений DAO.


Перш за все "сховища / об'єкти ORM"? Ви маєте на увазі організації ORM. Не існує такого поняття, як сховище ORM. По-друге, ORM зазвичай мають справу лише з утвореннями, тобто. доменні моделі. DAO мають справу з таблицями безпосередньо та абстрактним доступом до даних. Вони також повертають суб'єкти. Репозиторії - це найвища абстракція, яка пропонує інтерфейс колекції для отримання сутностей. DAO може бути сховищем, тобто. абстрагування фактичного механізму зберігання даних, пропонуючи йому інтерфейс, а також пропонуючи перегляд колекції (кеш) сутностей. DAO може використовувати ORM для взаємодії з базою даних та делегуванням операцій.
Пол-Себастьян Маноле

3
Погодьтеся з @brokenthorn. Найважливішим моментом у його коментарі є "сховища - це найвища абстракція", і ця абстракція стає необхідністю, коли ви хочете захистити свій доменний код від основної технології бази даних. Концепції драйверів ORM / Adapter / DB мають тенденцію просочуватися в DAO. Якщо у вас є програма, яка підтримує більш ніж одну технологію баз даних, або ви хочете, щоб ваш додаток не було заблоковано до бази даних, використання DAO безпосередньо з доменної моделі є недійсним.
Subhash Bhushan

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


0

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


DAO також може представляти колекції / предмети ...
Yousha Aleayoub

0

У весняних рамках є анотація, яка називається сховищем, а в описі цієї анотації є корисна інформація про сховище, яка, на мою думку, є корисною для цього обговорення.

Вказує, що анотований клас - це "репозиторій", спочатку визначений дизайном, керованим доменом (Evans, 2003), як "механізм інкапсуляції зберігання, пошуку та пошукової поведінки, що імітує колекцію об'єктів".

Команди, що реалізують традиційні шаблони Java EE, такі як "Об'єкт доступу до даних", також можуть застосовувати цей стереотип до класів DAO, хоча перед цим слід постаратися зрозуміти відмінність між об'єктом доступу до даних та сховищами стилю DDD. Ця анотація є стереотипом загального призначення, і окремі команди можуть звужувати свою семантику та використовувати за необхідності.

Клас, зазначений таким чином, анотований, є придатним для весняного перекладу DataAccessException при використанні спільно з PersistenceExceptionTranslationPostProcessor. Також пояснюється анотований клас щодо його ролі в загальній архітектурі додатків з метою інструментальних засобів, аспектів тощо.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.