Was ist der Unterschied zwischen DAO- und Repository-Mustern?

423

Was ist der Unterschied zwischen DAO- (Data Access Objects) und Repository-Mustern? Ich entwickle eine Anwendung mit Enterprise Java Beans (EJB3), Hibernate ORM als Infrastruktur und Domain-Driven Design (DDD) und Test-Driven Development (TDD) als Designtechniken.

Thurein
quelle

Antworten:

471

DAOist eine Abstraktion der Datenpersistenz .
Repositoryist eine Abstraktion einer Sammlung von Objekten .

DAOwürde näher an der Datenbank betrachtet werden, oft tabellenzentriert.
Repositorywürde als näher an der Domäne betrachtet und nur in aggregierten Wurzeln behandelt.

Repositorykönnte mit DAO's implementiert werden , aber Sie würden nicht das Gegenteil tun.

Außerdem ist a Repositoryim Allgemeinen eine engere Schnittstelle. Es sollte einfach eine Sammlung von Objekten sein, mit einem Get(id), Find(ISpecification), Add(Entity).

Eine Methode wie Updateist für a geeignet DAO, aber nicht für a. RepositoryBei Verwendung von a Repositorywerden Änderungen an Entitäten normalerweise von einer separaten UnitOfWork verfolgt.

Es scheint üblich zu sein, Implementierungen zu sehen, die als a Repositorybezeichnet werden und wirklich eher a sind DAO, und daher denke ich, dass es einige Verwirrung über den Unterschied zwischen ihnen gibt.

Quentin-Starin
quelle
26
Nun, Sie möchten nicht, dass Ihre DAO-Klasse Ihre IRepositorySchnittstelle buchstäblich implementiert . Sie möchten, dass Ihr Repository DAOs bei seiner Implementierung verwendet. Denken Sie daran, dass ein DAO ein Objekt pro Tabelle ist, während ein Repository fast immer mehrere DAOs verwenden muss, um eine einzelne Entität zu erstellen. Wenn Sie feststellen, dass dies nicht der Fall ist und Ihr Repository und Ihre Entität nur auf eine einzelne Tabelle zugreifen müssen, erstellen Sie höchstwahrscheinlich eine anämische Domäne.
Quentin-Starin
29
Ich habe festgestellt, dass in der .NET-Welt speziell der Begriff "Repository" verwendet wird, um sich auf das zu beziehen, was im Wesentlichen ein DAO ist. "DAO" ist eher ein Java-Begriff.
Wayne Molina
14
@ Thurein DAOs sind nicht pro Tabelle, das Muster abstrahiert nur den Zugriff auf Ihre Daten - Sie können das implementieren, wie Sie möchten (pro Tabelle, pro Gruppe oder Modell). Die empfohlene Methode besteht darin, Ihre DAOs immer basierend auf Ihrem Domain-Modell zu gestalten, anstatt die zugrunde liegende Persistenz zu berücksichtigen, da dies die Verwendung einfacher / klarer macht und Ihnen ein bisschen mehr Flexibilität bei der Persistenz gibt (z. B. stellen Sie sich vor, Sie benötigen sie ein DAO, das Ihre Daten in XML-Dateien speichert oder aus einer Nachrichtenwarteschlange anstatt aus der Datenbank abruft ...).
Stef
21
@Stef Ich bin anderer Meinung. A DAO liefert Daten per definitionem (a Datenzugriffsobjekt). Ein Repository gibt per Definition Domänenobjekte zurück. Es liegt auf der Hand, dass das Repository DAOs verwenden würde und nicht umgekehrt, da wir in OOP Domänenobjekte aus einem oder mehreren Datenobjekten zusammensetzen und nicht umgekehrt.
Mihai Danila
6
Warum ist ein Repository ein "Nur Lesen" -Konzept, während DAO "Lesen und Schreiben" ist?
Dennis
120

OK, denke ich kann besser erklären, was ich in die Kommentare geschrieben habe :). Grundsätzlich können Sie also beide als gleich ansehen, obwohl DAO ein flexibleres Muster als Repository ist. Wenn Sie beide verwenden möchten, verwenden Sie das Repository in Ihren DAOs. Ich werde jeden von ihnen unten erklären:

REPOSITORY:

Es ist ein Repository für einen bestimmten Objekttyp - es ermöglicht Ihnen, nach einem bestimmten Objekttyp zu suchen und diese zu speichern. Normalerweise werden NUR ein Objekttyp behandelt. ZB AppleRepositorywürde dir erlauben zu tun AppleRepository.findAll(criteria)oder AppleRepository.save(juicyApple). Beachten Sie, dass das Repository Domänenmodellbegriffe verwendet (keine DB-Begriffe - nichts damit zu tun, wie Daten irgendwo gespeichert werden).

Ein Repository speichert höchstwahrscheinlich alle Daten in derselben Tabelle, während das Muster dies nicht erfordert. Die Tatsache, dass es nur einen Datentyp verarbeitet, macht es logisch mit einer Haupttabelle verbunden (wenn es für die DB-Persistenz verwendet wird).

DAO - Datenzugriffsobjekt (mit anderen Worten - Objekt, mit dem auf Daten zugegriffen wird)

Ein DAO ist eine Klasse, die Daten für Sie findet (es ist meistens ein Finder, wird aber häufig auch zum Speichern der Daten verwendet). Das Muster beschränkt Sie nicht darauf, Daten desselben Typs zu speichern, sodass Sie problemlos ein DAO haben können, das verwandte Objekte findet / speichert.

ZB können Sie leicht UserDao haben, das Methoden wie verfügbar macht

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

Alle diese beziehen sich auf den Benutzer (und die Sicherheit) und können unter demselben DAO angegeben werden. Dies ist beim Repository nicht der Fall.

Schließlich

Beachten Sie, dass beide Muster wirklich dasselbe bedeuten (sie speichern Daten und abstrahieren den Zugriff darauf und sie werden beide näher am Domänenmodell ausgedrückt und enthalten kaum eine DB-Referenz), aber die Art und Weise, wie sie verwendet werden, kann geringfügig unterschiedlich sein, DAO etwas flexibler / allgemeiner, während das Repository etwas spezifischer und nur auf einen Typ beschränkt ist.

Stef
quelle
Wenn ich das richtig verstehe CarDescription, zB language_idwenn ich so etwas habe, zB als Fremdschlüssel - dann CarRepository.getAll(new Criteria(carOwner.id, language.id));ist es der richtige Weg, um herauszufinden, dass ich so etwas tun sollte: was mir alle Autos einer Sprache in einer bestimmten Sprache geben würde ?
Anzeigename
@StefanFalk, schauen Sie sich Spring Data an, damit können Sie viel schönere Anrufe tätigen. CarRepository.findByLanguageId(language.id)Zum Beispiel könnte das so geschrieben werden und Sie müssten nicht einmal den Code schreiben. Sie definieren einfach die Schnittstelle mit einer Methode mit diesem Namen und Spring Data kümmert sich um die Erstellung der Standardklassenimplementierung für Sie. Ziemlich ordentliches Zeug;)
Stef
2
Das Schöne an Spring Data ist, dass Sie die Abfragen nicht schreiben müssen, sondern nur eine Schnittstelle erstellen (wie das TodoRepository in Ihrem Beispiel, das die Methode hat findById). Und Sie sind praktisch fertig. Spring Data findet dann alle von Ihnen erstellten Schnittstellen, die die Repository-Schnittstelle erweitern, und erstellt die Klassen für Sie. Sie werden diese Klassen nie sehen und können keine neuen Instanzen erstellen, müssen dies jedoch nicht, da Sie die Schnittstelle einfach automatisch verdrahten und Spring das Repository-Objekt lokalisieren lassen können.
Stef
1
Schließlich müssen Sie Spring Data nicht verwenden, Sie können die Abfragemethoden auf die alte Art und Weise selbst schreiben (mithilfe der Kriterien-API usw.), aber Sie würden Ihr Leben nur ein bisschen komplexer gestalten ... Das könnten Sie sagen Sie hätten so mehr Flexibilität, aber das stimmt auch nicht, als ob Sie wirklich verrückt nach Ihren Abfragen werden möchten. Spring Data bietet Ihnen zwei Möglichkeiten, dies zu tun: die Annotation @Query, oder wenn das nicht funktioniert, können Sie es Erstellen Sie benutzerdefinierte Repositorys, die eine Erweiterung darstellen, mit der Sie die gleiche Leistung erzielen, als würden Sie Ihre eigene Implementierung von Grund auf neu schreiben.
Stef
2
"Aggregierter Stamm" ist ein Begriff, der häufig mit dem Repository-Muster verbunden ist. Ich weiß nicht, wie Sie das mit Ihrer Definition eines Repositorys verwenden würden.
Christian Strempfer
90

DAO- und Repository-Muster sind Möglichkeiten zur Implementierung von Data Access Layer (DAL). Beginnen wir also zuerst mit DAL.

Objektorientierte Anwendungen, die auf eine Datenbank zugreifen, müssen über eine Logik für den Datenbankzugriff verfügen. Um den Code sauber und modular zu halten, wird empfohlen, die Datenbankzugriffslogik in ein separates Modul zu isolieren. In der Schichtarchitektur ist dieses Modul DAL.

Bisher haben wir nicht über eine bestimmte Implementierung gesprochen: nur ein allgemeines Prinzip, das die Datenbankzugriffslogik in ein separates Modul einfügt.

Wie können wir dieses Prinzip nun umsetzen? Ein bekannter Weg, dies zu implementieren, insbesondere mit Frameworks wie Hibernate, ist das DAO-Muster.

Das DAO-Muster ist eine Methode zum Generieren von DAL, bei der normalerweise jede Domänenentität über ein eigenes DAO verfügt. Zum Beispiel Userund UserDao, Appointmentund AppointmentDaousw. Ein Beispiel für DAO mit Ruhezustand: http://gochev.blogspot.ca/2009/08/hibernate-generic-dao.html .

Was ist dann das Repository-Muster? Wie DAO ist auch das Repository-Muster ein Weg, um DAL zu erreichen. Der Hauptpunkt im Repository-Muster ist, dass es aus Client / Benutzer-Sicht als Sammlung aussehen oder sich so verhalten sollte. Was bedeutet, sich wie eine Sammlung zu verhalten, ist nicht, dass sie wie eine Sammlung instanziiert werden mussCollection collection = new SomeCollection() . Stattdessen bedeutet dies, dass Vorgänge wie Hinzufügen, Entfernen, Enthalten usw. unterstützt werden sollen. Dies ist die Essenz des Repository-Musters.

In der Praxis wird beispielsweise bei Verwendung des Ruhezustands das Repository-Muster mit DAO realisiert. Das heißt, eine Instanz von DAL kann gleichzeitig eine Instanz von DAO-Muster und Repository-Muster sein.

Das Repository-Muster ist nicht unbedingt etwas, das man auf DAO aufbaut (wie einige vielleicht vorschlagen). Wenn DAOs mit einer Schnittstelle entworfen wurden, die die oben genannten Operationen unterstützt, handelt es sich um eine Instanz des Repository-Musters. Denken Sie darüber nach: Wenn DAOs bereits eine sammlungsähnliche Reihe von Operationen bereitstellen, was ist dann die Notwendigkeit einer zusätzlichen Ebene darüber?

Nazar Merza
quelle
5
"Wenn DAOs bereits eine sammlungsähnliche Reihe von Operationen bereitstellen, was ist dann die Notwendigkeit einer zusätzlichen Schicht darüber?" Angenommen, Sie modellieren eine Zoohandlung und haben eine Tabelle 'PetType' mit verschiedenen Tieren und ihren Attributen (Name: "Katze", Typ: "Säugetier" usw.), auf die durch eine Tabelle 'Haustier' der konkreten Haustiere verwiesen wird im Laden haben (Name: "Katniss", Rasse: "Calico" usw.). Wenn Sie ein Tier eines Typs hinzufügen möchten, der noch nicht in der Datenbank enthalten ist, können Sie mithilfe eines Repositorys die beiden separaten DAO-Aufrufe (einen zum Erstellen von PetType und den anderen für das Haustier) in einer Methode gruppieren, um eine Kopplung in DAOs zu vermeiden
Matt
1
Hervorragende Erklärung, Sir!
Paul-Sebastian Manole
74

Ehrlich gesagt sieht dies nach einer semantischen Unterscheidung aus, nicht nach einer technischen Unterscheidung. Der Ausdruck Datenzugriffsobjekt bezieht sich überhaupt nicht auf eine "Datenbank". Und obwohl Sie es datenbankzentriert gestalten könnten, würden die meisten Leute dies als Konstruktionsfehler betrachten.

Der Zweck des DAO besteht darin, die Implementierungsdetails des Datenzugriffsmechanismus zu verbergen. Wie unterscheidet sich das Repository-Muster? Soweit ich das beurteilen kann, ist es das nicht. Die Aussage, dass ein Repository sich von einem DAO unterscheidet , weil Sie mit einer Sammlung von Objekten arbeiten / diese zurückgeben, kann nicht richtig sein. DAOs können auch Sammlungen von Objekten zurückgeben.

Alles, was ich über das Repository-Muster gelesen habe, scheint auf dieser Unterscheidung zu beruhen: schlechtes DAO-Design vs. gutes DAO-Design (auch bekannt als Repository-Design-Muster).

rakehell404
quelle
5
Ja, stimme vollkommen zu, sie sind im Wesentlichen gleich. DAO klingt eher DB-bezogen, ist es aber nicht. Wie bei Repository handelt es sich lediglich um eine Abstraktion, mit der ausgeblendet wird, wo und wie sich Daten befinden.
Stef
+1 Für diese Aussage. Ehrlich gesagt sieht dies nach einer semantischen Unterscheidung aus, nicht nach einer technischen Unterscheidung. Der Ausdruck Datenzugriffsobjekt bezieht sich überhaupt nicht auf eine "Datenbank".
Sudhakar Chavali
1
Beim Vergleich von Repositorys und Sammlungen geht es nicht darum, dass sie Sammlungen von Objekten handeln / zurückgeben, sondern dass sich Repositorys so verhalten, als wären sie selbst Sammlungen. In Java bedeutet dies beispielsweise, dass ein Repository keine Aktualisierungsmethode hat, da ein Objekt in einer Sammlung beim Ändern automatisch aktualisiert wird (da Java-Sammlungen nur Verweise auf Objekte speichern).
Christoph Böhme
17

Repository ist ein abstrakterer domänenorientierter Begriff, der Teil des Domain Driven Design ist. Er ist Teil Ihres Domain-Designs und eine gemeinsame Sprache. DAO ist eine technische Abstraktion für die Datenzugriffstechnologie. Das Repository befasst sich nur mit der Verwaltung vorhandener Daten und Fabriken zur Erstellung von Daten.

Überprüfen Sie diese Links:

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

Mohamed Abed
quelle
6

Der Hauptunterschied besteht darin, dass ein Repository den Zugriff auf die Aggregatwurzeln in einem Aggregat verwaltet, während DAO den Zugriff auf Entitäten verwaltet. Daher ist es üblich, dass ein Repository die tatsächliche Persistenz der aggregierten Wurzeln an ein DAO delegiert. Da der aggregierte Stamm den Zugriff der anderen Entitäten verarbeiten muss, muss er diesen Zugriff möglicherweise an andere DAOs delegieren.

Pablochacin
quelle
5

DAO bietet eine Abstraktion für Datenbank- / Datendateien oder andere Persistenzmechanismen, sodass die Persistenzschicht ohne Kenntnis der Implementierungsdetails manipuliert werden kann.

Während in Repository-Klassen mehrere DAO-Klassen innerhalb einer einzelnen Repository-Methode verwendet werden können, um eine Operation aus der "App-Perspektive" auszuführen. Verwenden Sie also nicht mehrere DAO auf Domänenebene, sondern das Repository, um dies zu erledigen. Das Repository ist eine Schicht, die einige Anwendungslogiken enthalten kann, z. B .: Wenn Daten im In-Memory-Cache verfügbar sind, rufen Sie sie andernfalls aus dem Cache ab. Rufen Sie andernfalls Daten aus dem Netzwerk ab und speichern Sie sie beim nächsten Abruf im In-Memory-Cache.

Rahul Rastogi
quelle
3

Repository sind nichts anderes als gut gestaltete DAO.

ORM sind tabellenzentriert, aber nicht DAO.

Es ist nicht erforderlich, mehrere DAO im Repository zu verwenden, da DAO selbst mit ORM-Repositorys / -Entitäten oder jedem DAL-Anbieter genau dasselbe tun kann, unabhängig davon, wo und wie ein Auto bestehen bleibt. 1 Tabelle, 2 Tabellen, n Tabellen, eine halbe Tabelle, a Webdienst, eine Tabelle und ein Webdienst usw. Dienste verwenden mehrere DAO / Repositorys.

Mein eigenes DAO, sagen wir, CarDao befasst sich nur mit Auto-DTO, ich meine, nehme nur Auto-DTO als Eingabe und gebe nur Auto-DTO oder Auto-DTO-Sammlungen als Ausgabe zurück.

Genau wie das Repository ist DAO tatsächlich ein IoC für die Geschäftslogik, sodass Persistenzschnittstellen nicht durch Persistenzstrategien oder Vermächtnisse eingeschüchtert werden können. DAO kapselt sowohl die Persistenzstrategie als auch die domänenbezogene Persistenzschnittstelle. Repository ist nur ein weiteres Wort für diejenigen, die nicht verstanden haben, was eine genau definierte DAO-Aktualität ist.

Cyril
quelle
Zuallererst "ORM-Repositorys / Entitäten"? Sie meinen ORM-Entitäten. Es gibt kein Repository für ORMs. Zweitens befassen sich ORMs normalerweise nur mit Entitäten, dh. Domänenmodelle. DAOs befassen sich direkt mit Tabellen und dem abstrakten Datenzugriff. Sie geben auch Entitäten zurück. Repositorys sind die höchste Abstraktion und bieten eine Sammlungsschnittstelle zum Abrufen von Entitäten. Ein DAO kann ein Repository sein, dh. Abstrahieren der eigentlichen Speicher-Engine, Anbieten einer Schnittstelle und einer Sammlungsansicht von (Cache-) Entitäten. Ein DAO kann ein ORM verwenden, um eine Schnittstelle zur Datenbank herzustellen und Entitätsoperationen zu delegieren.
Paul-Sebastian Manole
3
Stimmen Sie mit @brokenthorn überein. Der wichtigste Punkt in seinem Kommentar ist "Repositorys sind die höchste Abstraktion", und diese Abstraktion wird zu einer Notwendigkeit, wenn Sie Ihren Domänencode vor der zugrunde liegenden Datenbanktechnologie schützen möchten. ORM / Adapter / DB-Treiberkonzepte neigen dazu, in DAOs zu gelangen. Wenn Sie eine Anwendung haben, die mehr als eine Datenbanktechnologie unterstützt, oder wenn Sie möchten, dass Ihre App nicht an eine Datenbank gebunden ist, ist die Verwendung von DAOs direkt aus dem Domänenmodell kein Problem.
Subhash Bhushan
2

Versuchen Sie herauszufinden, ob DAO oder das Repository-Muster für die folgende Situation am besten geeignet sind: Stellen Sie sich vor, Sie möchten eine einheitliche Datenzugriffs-API für einen dauerhaften Mechanismus für verschiedene Arten von Datenquellen wie RDBMS, LDAP, OODB, XML-Repositorys und bereitstellen flache Dateien.

Beachten Sie bei Interesse auch die folgenden Links:

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
quelle
0

in einem sehr einfachen Satz: Der wesentliche Unterschied besteht darin, dass Repositorys Sammlungen darstellen, während DAOs näher an der Datenbank liegen und häufig weitaus tabellenzentrierter sind.

Alireza Rahmani Khalili
quelle
DAO kann auch Sammlungen / Objekte darstellen ...
Yousha Aleayoub vor
0

Im Frühjahrs-Framework gibt es eine Annotation namens Repository, und in der Beschreibung dieser Annotation gibt es nützliche Informationen über das Repository, die meiner Meinung nach für diese Diskussion nützlich sind.

Gibt an, dass eine mit Anmerkungen versehene Klasse ein "Repository" ist, das ursprünglich von Domain-Driven Design (Evans, 2003) als "Mechanismus zum Einkapseln von Speicher-, Abruf- und Suchverhalten, das eine Sammlung von Objekten emuliert" definiert wurde.

Teams, die traditionelle Java EE-Muster wie "Datenzugriffsobjekt" implementieren, können dieses Stereotyp auch auf DAO-Klassen anwenden. Es sollte jedoch darauf geachtet werden, die Unterscheidung zwischen Datenzugriffsobjekt- und DDD-ähnlichen Repositorys zu verstehen, bevor Sie dies tun. Diese Anmerkung ist ein allgemeines Stereotyp, und einzelne Teams können ihre Semantik einschränken und gegebenenfalls verwenden.

Eine so kommentierte Klasse kann in Verbindung mit einem PersistenceExceptionTranslationPostProcessor für die Spring DataAccessException-Übersetzung verwendet werden. Die mit Anmerkungen versehene Klasse wird auch hinsichtlich ihrer Rolle in der gesamten Anwendungsarchitektur zum Zweck von Werkzeugen, Aspekten usw. geklärt.

Ali Yeganeh
quelle