Jaka jest różnica między wzorcami DAO i repozytorium?

423

Jaka jest różnica między obiektami dostępu do danych (DAO) a wzorcami repozytoriów? Tworzę aplikację przy użyciu Enterprise Java Beans (EJB3), Hibernate ORM jako infrastruktury, oraz Domain-Driven Design (DDD) i Test-Driven Development (TDD) jako techniki projektowania.

Thurein
źródło

Odpowiedzi:

471

DAOjest abstrakcją trwałości danych .
Repositoryjest abstrakcją zbioru obiektów .

DAObyłoby uważane za bliższe bazy danych, często koncentrujące się na tabelach.
Repositorybędzie uważany za bliższy do Domeny, zajmujący się tylko w Zbiorczych Korzeniach.

Repositorymożna zaimplementować za pomocą DAO's, ale nie zrobiłbyś czegoś przeciwnego.

Ponadto a Repositoryjest ogólnie węższym interfejsem. Powinno być po prostu zbiorem obiektów, z Get(id), Find(ISpecification), Add(Entity).

Metoda podobna Updatejest odpowiednia w przypadku DAO, ale nie w Repositoryprzypadku - gdy używasz Repository, zmiany w jednostkach byłyby zwykle śledzone przez oddzielne UnitOfWork.

Wydaje się, że implementacje nazywane Repositorysą w rzeczywistości bardziej DAO, a zatem myślę, że istnieje pewne zamieszanie co do różnicy między nimi.

quentin-starin
źródło
26
Nie chciałbyś, aby twoja klasa DAO dosłownie implementowała twój IRepositoryinterfejs. Chcesz, aby Twoje repozytorium używało DAO w swojej implementacji. Pamiętaj, że DAO będzie obiektem na tabelę, podczas gdy Repozytorium prawie zawsze będzie musiało używać wielu DAO do zbudowania pojedynczej Jednostki. Jeśli okaże się, że tak nie jest, że Twoje repozytorium i jednostka potrzebują tylko dostępu do jednej tabeli, najprawdopodobniej budujesz domenę anemiczną.
quentin-starin
29
Zauważyłem, że w świecie .NET termin „repozytorium” jest używany w odniesieniu do tego, co zasadniczo jest DAO; „DAO” jest bardziej terminem Java.
Wayne Molina,
14
@Thurein DAO-s nie są na tabelę, wzorzec tylko abstrahuje dostęp do twoich danych - możesz zaimplementować to, co chcesz (dla tabeli, dla grupy lub modeli). Zalecanym sposobem jest zawsze kształtowanie DAO w oparciu o model domeny, a nie wzięcie pod uwagę trwałej trwałości, ponieważ ułatwia to / upraszcza obsługę i daje nieco większą elastyczność w jej utrzymywaniu (np. Wyobraź sobie, że będziesz potrzebować DAO, który przechowuje dane w plikach XML lub pobiera je z kolejki komunikatów zamiast z bazy danych ...).
Stef
21
@Stef Nie zgadzam się. DAO zwraca dane z samej swojej definicji ( obiekt dostępu do danych ). Repozytorium z definicji zwraca obiekty domeny. Powinno to uzasadniać, że repozytorium będzie używać DAO, a nie na odwrót, ponieważ w OOP komponujemy obiekty domeny z jednego lub więcej obiektów danych, a nie na odwrót.
Mihai Danila,
6
Dlaczego repozytorium jest pojęciem „tylko do odczytu”, podczas gdy DAO to „odczyt i zapis”?
Dennis,
120

OK, myślę, że mogę lepiej wyjaśnić, co umieściłem w komentarzach :). Zasadniczo możesz zobaczyć oba te same, chociaż DAO jest bardziej elastycznym wzorcem niż Repozytorium. Jeśli chcesz korzystać z obu, użyjesz Repozytorium w swoich DAO. Wyjaśnię każdy z nich poniżej:

MAGAZYN:

Jest to repozytorium określonego typu obiektów - umożliwia wyszukiwanie określonego typu obiektów oraz ich przechowywanie. Zwykle obsługuje TYLKO jeden typ obiektów. Np. AppleRepositoryPozwoli ci to zrobić AppleRepository.findAll(criteria)lubAppleRepository.save(juicyApple) . Pamiętaj, że repozytorium używa terminów modelu domeny (nie terminów DB - nic nie ma związku z tym, jak dane są utrwalane w dowolnym miejscu).

Repozytorium najprawdopodobniej będzie przechowywać wszystkie dane w tej samej tabeli, podczas gdy wzorzec tego nie wymaga. Fakt, że obsługuje tylko jeden typ danych, sprawia, że ​​logicznie jest on połączony z jedną główną tabelą (jeśli jest używany do trwałości DB).

DAO - obiekt dostępu do danych (innymi słowy - obiekt używany do uzyskania dostępu do danych)

DAO to klasa, która lokalizuje dane dla Ciebie (jest to przeważnie wyszukiwarka, ale zwykle jest używana do przechowywania danych). Wzorzec nie ogranicza Cię do przechowywania danych tego samego typu, dlatego możesz łatwo mieć DAO, który lokalizuje / przechowuje powiązane obiekty.

Np. Możesz łatwo mieć Userexe, który udostępnia metody takie jak

Collection<Permission> findPermissionsForUser(String userId)
User findUser(String userId)
Collection<User> findUsersForPermission(Permission permission)

Wszystkie te są związane z użytkownikiem (i bezpieczeństwem) i można je określić w ramach tego samego DAO. Nie dotyczy to repozytorium.

Wreszcie

Zauważ, że oba wzorce naprawdę oznaczają to samo (przechowują dane i wyodrębniają dostęp do nich i oba wyrażone są bliżej modelu domeny i prawie nie zawierają żadnych odniesień DB), ale sposób ich użycia może być nieco inny, ponieważ DAO nieco bardziej elastyczny / ogólny, podczas gdy Repozytorium jest nieco bardziej szczegółowe i ogranicza się tylko do określonego typu.

Stef
źródło
Jeśli dobrze to rozumiem, np. Mam coś takiego jak CarDescriptionnp language_id. Klucz obcy - aby odzyskać, że powinienem zrobić coś takiego: CarRepository.getAll(new Criteria(carOwner.id, language.id));co dałoby mi wszystkie samochody w danym języku - to właściwy sposób, aby to zrobić ?
nazwa wyświetlana
@StefanFalk, spójrz na Spring Data, pozwala na wykonywanie znacznie ładniejszych połączeń niż to. np. można to napisać tak CarRepository.findByLanguageId(language.id), że nie trzeba nawet pisać kodu, wystarczy zdefiniować interfejs za pomocą metody o tej nazwie, a Spring Data zajmie się zbudowaniem domyślnej implementacji klasy. Całkiem fajne rzeczy;)
Stef
2
Piękno Spring Data polega na tym, że tak naprawdę nie musisz pisać zapytań, po prostu tworzysz interfejs (taki jak ten TodoRepository w twoim przykładzie, który ma metodę findById). I jesteś praktycznie skończony. W takim razie Spring Data znajduje wszystkie utworzone przez ciebie interfejsy, które rozszerzają interfejs repozytorium i tworzy dla ciebie klasy. Nigdy nie zobaczysz tych klas i nie będziesz mógł tworzyć nowych instancji, ale nie musisz tego robić, ponieważ możesz po prostu automatycznie uruchomić interfejs i pozwolić Springowi zlokalizować ten obiekt repozytorium.
Stef
1
Wreszcie, nie musisz używać Spring Data, możesz przejść stary sposób pisania metod zapytań samodzielnie (używając Criteria API itp.), Ale po prostu uczynisz swoje życie nieco bardziej złożonym ... Możesz tak powiedzieć miałbyś większą elastyczność, ale nie jest to prawdą, jeśli naprawdę chcesz zwariować na punkcie swoich zapytań, Spring Data pozwala na dwa sposoby: adnotację @Query lub jeśli to nie działa, możesz twórz niestandardowe repozytoria, które są rozszerzeniem, które daje taką samą moc, jakbyś pisał własną implementację od zera.
Stef
2
„Zagregowany katalog główny” to termin często związany z wzorcem repozytorium. Nie wiem, jak byś to wykorzystał w swojej definicji repozytorium.
Christian Strempfer,
90

Wzorzec DAO i repozytorium to sposoby implementacji warstwy dostępu do danych (DAL). Zacznijmy od DAL, po pierwsze.

Aplikacje obiektowe, które uzyskują dostęp do bazy danych, muszą mieć pewną logikę do obsługi dostępu do bazy danych. Aby zachować czystość i modułowość kodu, zaleca się odizolowanie logiki dostępu do bazy danych w osobnym module. W architekturze warstwowej tym modułem jest DAL.

Jak dotąd nie rozmawialiśmy o żadnej konkretnej implementacji: tylko ogólna zasada umieszczania logiki dostępu do bazy danych w osobnym module.

Jak możemy wdrożyć tę zasadę? Znanym sposobem implementacji tego, szczególnie w ramach takich jak Hibernacja, jest wzorzec DAO.

Wzorzec DAO to sposób generowania DAL, w którym zazwyczaj każda jednostka domeny ma swoje własne DAO. Na przykład Useri UserDao, Appointmenti AppointmentDaoitp. Przykład DAO z Hibernacją: http://gochev.blogspot.ca/2009/08/hibernate-generic-dao.html .

Co to jest wzorzec repozytorium? Podobnie jak DAO, wzór repozytorium jest również sposobem na osiągnięcie DAL. Głównym punktem wzorca repozytorium jest to, że z perspektywy klienta / użytkownika powinien on wyglądać lub zachowywać się jak kolekcja. Zachowanie się jak kolekcja nie oznacza, że ​​należy ją utworzyć Collection collection = new SomeCollection(). Zamiast tego oznacza, że ​​powinien obsługiwać operacje takie jak dodawanie, usuwanie, zawiera itp. To jest istota wzorca repozytorium.

W praktyce, na przykład w przypadku użycia hibernacji, wzór repozytorium jest realizowany za pomocą DAO. To jest wystąpienie DAL może być zarówno w tym samym wystąpieniu wzorca DAO i wzorca repozytorium.

Wzorzec repozytorium niekoniecznie jest czymś, co buduje się na DAO (jak niektórzy mogą sugerować). Jeśli DAO są zaprojektowane z interfejsem, który obsługuje wyżej wymienione operacje, jest to instancja wzorca repozytorium. Pomyśl o tym, jeśli DAO już zapewniają zbiór operacji podobny do kolekcji, to jaka jest potrzeba dodatkowej warstwy na nim?

Nazar Merza
źródło
5
„Jeśli DAO już zapewniają zbiór operacji podobny do kolekcji, to po co jest potrzebna dodatkowa warstwa na nim?” Załóżmy, że modelujesz sklep zoologiczny i masz tabelę „PetType” z różnymi zwierzętami i ich atrybutami (nazwa: „Kot”, typ: „Ssak” itp.), Do których odwołuje się tabela „Zwierzę domowe” konkretnych zwierząt domowych mają w sklepie (nazwa: „Katniss”, rasa: „Calico” itp.). Jeśli chcesz dodać zwierzę typu, którego jeszcze nie ma w bazie danych, możesz użyć repozytorium, aby zgrupować dwa osobne wywołania DAO (jedno dla utworzenia PetType, a drugie dla zwierzaka) za pomocą jednej metody, unikając łączenia w DAO
Matt
1
Doskonałe wyjaśnienie, Sir!
Paul-Sebastian Manole,
74

Szczerze mówiąc, wygląda to na rozróżnienie semantyczne, a nie techniczne. Fraza Obiekt dostępu do danych w ogóle nie odnosi się do „bazy danych”. I chociaż można zaprojektować go tak, aby był zorientowany na bazę danych, myślę, że większość ludzi pomyślałaby o zrobieniu tego wady projektowej.

Celem DAO jest ukrycie szczegółów implementacji mechanizmu dostępu do danych. Czym różni się wzorzec repozytorium? O ile wiem, nie jest. Mówienie o repozytorium różni się od DAO, ponieważ masz do czynienia z / zwracaniem kolekcji obiektów, nie może mieć racji; DAO mogą również zwracać kolekcje obiektów.

Wszystko, co przeczytałem na temat wzorca repozytorium, wydaje się polegać na tym rozróżnieniu: zły projekt DAO vs. dobry projekt DAO (inaczej wzorzec projektu repozytorium).

rakehell404
źródło
5
tak, całkowicie się zgadzam, są zasadniczo takie same. DAO wydaje się bardziej związane z DB, ale tak nie jest. Podobnie jak Repozytorium, jest to tylko abstrakcja służąca do ukrycia miejsca i sposobu lokalizacji danych.
Stef
+1 za to oświadczenie. Szczerze mówiąc, wygląda to na rozróżnienie semantyczne, a nie techniczne. Fraza Obiekt dostępu do danych w ogóle nie odnosi się do „bazy danych”.
Sudhakar Chavali
1
Podczas porównywania repozytoriów i kolekcji nie chodzi o to, że zajmują się one / zwracają kolekcje obiektów, ale że repozytoria zachowują się tak, jakby same były kolekcjami. Na przykład w Javie oznacza to, że repozytorium nie ma metody aktualizacji, ponieważ podczas modyfikowania obiektu w kolekcji jest on automatycznie aktualizowany (ponieważ kolekcje Java przechowują tylko odniesienia do obiektów).
Christoph Böhme
17

Repozytorium jest bardziej abstrakcyjnym terminem zorientowanym na domenę, który jest częścią projektu opartego na domenie, jest częścią projektu domeny i wspólnego języka, DAO jest abstrakcją techniczną dla technologii dostępu do danych, repozytorium dotyczy tylko zarządzania istniejącymi danymi i fabrykami w celu tworzenia dane.

sprawdź te linki:

http://warren.mayocchi.com/2006/07/27/repository-or-dao/ http://fabiomaulo.blogspot.com/2009/09/repository-or-dao-repository.html

Mohamed Abed
źródło
6

Kluczową różnicą jest to, że repozytorium obsługuje dostęp do zagregowanych katalogów głównych w agregacie, podczas gdy DAO obsługuje dostęp do encji. Dlatego powszechne jest, że repozytorium deleguje rzeczywistą trwałość zagregowanych katalogów głównych do DAO. Ponadto, ponieważ zagregowany katalog główny musi obsługiwać dostęp do innych podmiotów, może być konieczne przekazanie tego dostępu innym podmiotom DAO.

pablochacyna
źródło
5

DAO zapewnia abstrakcję plików bazy danych / danych lub dowolnego innego mechanizmu trwałości, dzięki czemu warstwą trwałości można manipulować bez znajomości szczegółów jej implementacji.

Podczas gdy w klasach repozytorium można użyć wielu klas DAO w jednej metodzie repozytorium, aby wykonać operację z „perspektywy aplikacji”. Zamiast używać wielu DAO w warstwie domeny, użyj repozytorium, aby to zrobić. Repozytorium jest warstwą, która może zawierać pewną logikę aplikacji, taką jak: Jeśli dane są dostępne w pamięci podręcznej w pamięci, następnie pobierz je z pamięci podręcznej, w przeciwnym razie pobierz dane z sieci i zapisz w pamięci podręcznej w pamięci do następnego pobrania.

Rahul Rastogi
źródło
3

Repozytorium to nic innego jak dobrze zaprojektowane DAO.

ORM są skoncentrowane na stole, ale nie DAO.

Nie ma potrzeby używania kilku DAO w repozytorium, ponieważ samo DAO może zrobić dokładnie to samo z repozytoriami / podmiotami ORM lub dowolnym dostawcą DAL, bez względu na to, gdzie i jak utrwalony jest samochód 1 tabela, 2 tabele, n tabele, pół tabeli, a serwis internetowy, tabela i serwis internetowy itp. Usługi korzystają z kilku DAO / repozytoriów.

Moje własne DAO, powiedzmy, CarDA zajmuje się tylko Car DTO, to znaczy, bierze Car DTO tylko na wejściu i zwraca tylko kolekcje samochodów DTO lub samochodów DTO na wyjściu.

Tak więc, podobnie jak Repozytorium, DAO faktycznie jest IoC dla logiki biznesowej, pozwalając interfejsom persytencji nie być zastraszanym przez strategie perswazji lub dziedzictwo. DAO zarówno zawiera strategię trwałości, jak i udostępnia interfejs persytencji związany z domeną. Repozytorium to tylko jedno słowo dla tych, którzy nie zrozumieli, czym właściwie jest dobrze zdefiniowane DAO.

Cyryl
źródło
Przede wszystkim „repozytoria / podmioty ORM”? Masz na myśli podmioty ORM. Nie ma czegoś takiego jak repozytorium ORM. Po drugie, ORM zwykle dotyczą tylko podmiotów, tj. modele domen. DAO zajmują się bezpośrednio tabelami i dostępem do danych abstrakcyjnych. Zwracają również byty. Repozytoria są najwyższą abstrakcją, oferując interfejs kolekcji do uzyskiwania encji. DAO może być repozytorium, tj. wyodrębnienie rzeczywistego silnika pamięci, oferując interfejs, a także oferując widok kolekcji jednostek (pamięci podręcznej). DAO może używać ORM do łączenia się z bazą danych i delegowania operacji encji.
Paul-Sebastian Manole
3
Zgadzam się z @brokenthorn. Najważniejszym punktem jego komentarza jest „Repozytoria są najwyższą abstrakcją”, a ta abstrakcja staje się koniecznością, gdy chcesz chronić swój kod domeny przed bazową technologią baz danych. Koncepcje ORM / Adapter / DB Driver mają tendencję do wycieku do DAO. Jeśli masz aplikację obsługującą więcej niż jedną technologię bazodanową lub jeśli nie chcesz, aby twoja aplikacja była blokowana w bazie danych, używanie DAO bezpośrednio z modelu domeny jest niemożliwe.
Subhash Bhushan
2

Spróbuj dowiedzieć się, czy DAO lub wzorzec repozytorium najlepiej nadaje się do następującej sytuacji: Wyobraź sobie, że chcesz zapewnić jednolity interfejs API dostępu do danych dla trwałego mechanizmu dla różnych typów źródeł danych, takich jak RDBMS, LDAP, OODB, repozytoria XML i płaskie pliki.

W razie zainteresowania zapoznaj się również z następującymi linkami:

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
źródło
0

w bardzo prostym zdaniu: Istotną różnicą jest to, że Repozytoria reprezentują kolekcje, podczas gdy DAO są bliżej bazy danych, często bardziej skoncentrowane na tabelach.

Alireza Rahmani Khalili
źródło
DAO może również reprezentować kolekcje / obiekty ...
Yousha Aleayoub
0

W strukturze wiosennej znajduje się adnotacja zwana repozytorium, aw opisie tej adnotacji znajdują się przydatne informacje o repozytorium, które moim zdaniem są przydatne w tej dyskusji.

Wskazuje, że klasa z adnotacjami jest „repozytorium”, pierwotnie zdefiniowanym przez Domain-Driven Design (Evans, 2003) jako „mechanizm enkapsulacji przechowywania, pobierania i wyszukiwania, który emuluje kolekcję obiektów”.

Zespoły wdrażające tradycyjne wzorce Java EE, takie jak „Obiekt dostępu do danych”, mogą również zastosować ten stereotyp do klas DAO, jednak należy dołożyć starań, aby zrozumieć różnicę między Obiektem dostępu do danych a repozytoriami w stylu DDD. Ta adnotacja jest stereotypem ogólnego zastosowania, a poszczególne zespoły mogą zawęzić swoją semantykę i stosować ją odpowiednio.

Tak opisana klasa kwalifikuje się do tłumaczenia Spring DataAccessException, jeśli jest używana w połączeniu z PersistenceExceptionTranslationPostProcessor. Klasa z adnotacjami została również wyjaśniona co do jej roli w ogólnej architekturze aplikacji do celów oprzyrządowania, aspektów itp.

Ali Yeganeh
źródło