DAO versus repository-patronen

1. Overzicht

Vaak worden de implementaties van repository en DAO als onderling uitwisselbaar beschouwd, vooral in datacentrische apps. Dit zorgt voor verwarring over hun verschillen.

In dit artikel bespreken we de verschillen tussen DAO- en Repository-patronen.

2. DAO-patroon

Het Data Access Object Pattern, ook bekend als DAO-patroon, is een abstractie van gegevenspersistentie en wordt beschouwd als dichter bij de onderliggende opslag, die vaak tabelgeoriënteerd is.

Daarom komen onze DAO's in veel gevallen overeen met databasetabellen, waardoor het een eenvoudiger manier is om gegevens uit de opslag te verzenden / op te halen en de lelijke zoekopdrachten te verbergen.

Laten we eens kijken naar een eenvoudige implementatie van het DAO-patroon.

2.1. Gebruiker

Laten we eerst een basis maken Gebruiker domeinklasse:

openbare klasse Gebruiker {privé Lange id; private String gebruikersnaam; private String voornaam; privé String-e-mail; // getters en setters}

2.2. Gebruiker

Vervolgens maken we het Gebruiker interface die eenvoudige CRUD-bewerkingen biedt voor het Gebruiker domein:

openbare interface User Dao {void create (User user); Gebruiker gelezen (lange id); ongeldige update (gebruiker gebruiker); void delete (String gebruikersnaam); }

2.3. GebruikersdateImpl

Als laatste maken we het GebruikersdateImpl klasse die de Gebruiker koppel:

public class UserensionalImpl implementeert User Dao {private final EntityManager entityManager; @Override public void create (User user) {entityManager.persist (user); } @Override public User read (lange id) {return entityManager.find (User.class, id); } // ...}

Hier hebben we voor de eenvoud de JPA gebruikt EntityManager interface om te communiceren met onderliggende opslag en om een ​​gegevenstoegangsmechanisme te bieden voor het Gebruiker domein.

3. Repository-patroon

Volgens het boek van Eric Evans Domeingestuurd ontwerp, de "Repository is een mechanisme voor het inkapselen van opslag-, ophaal- en zoekgedrag, dat een verzameling objecten emuleert."

Evenzo, volgens Patronen van Enterprise Application Architecture, het "Bemiddelt tussen de domein- en gegevenstoewijzingslagen met behulp van een collectie-achtige interface voor toegang tot domeinobjecten."

Met andere woorden, een repository behandelt ook gegevens en verbergt query's die vergelijkbaar zijn met DAO. Het bevindt zich echter op een hoger niveau, dichter bij de bedrijfslogica van een app.

Bijgevolg kan een repository een DAO gebruiken om gegevens uit de database op te halen en een domeinobject te vullen. Of het kan de gegevens van een domeinobject voorbereiden en naar een opslagsysteem sturen met behulp van een DAO voor persistentie.

Laten we eens kijken naar een eenvoudige implementatie van het repository-patroon voor het Gebruiker domein.

3.1. UserRepository

Laten we eerst het UserRepository koppel:

openbare interface UserRepository {User get (lange id); void add (gebruiker gebruiker); ongeldige update (gebruiker gebruiker); ongeldig verwijderen (gebruiker gebruiker); }

Hier hebben we een paar veelgebruikte methoden toegevoegd, zoals krijgen, toevoegen, bijwerken, en verwijderen om te werken met de verzameling objecten.

3.2. UserRepositoryImpl

Vervolgens maken we het UserRepositoryImpl klasse die een implementatie biedt van de UserRepository koppel:

openbare klasse UserRepositoryImpl implementeert UserRepository {privé User DaoImpl userbaoImpl; @Override openbare gebruiker get (lange id) {gebruiker gebruiker = userbaoImpl.read (id); terugkeer gebruiker; } @Override public void add (User user) {userensionalImpl.create (user); } // ...}

Hier hebben we de GebruikersdateImpl om gegevens uit de database te verzenden / op te halen.

Tot nu toe kunnen we zeggen dat de implementaties van DAO en repository erg op elkaar lijken omdat de Gebruiker klasse is een bloedarm domein. En een repository is gewoon een andere laag over de datatoegangslaag (DAO).

DAO lijkt echter een perfecte kandidaat om toegang te krijgen tot de gegevens, en een repository is een ideale manier om een ​​zakelijke use-case te implementeren.

4. Repository-patroon met meerdere DAO's

Laten we, om de laatste verklaring duidelijk te begrijpen, onze verbeteren Gebruiker domein om een ​​zakelijk gebruiksscenario af te handelen.

Stel je voor dat we een socialemediaprofiel van een gebruiker willen voorbereiden door zijn Twitter-tweets, Facebook-berichten en meer te verzamelen.

4.1. Tweet

Eerst maken we het Tweet klasse met een paar eigenschappen die de tweet-informatie bevatten:

openbare klasse Tweet {privé String e-mail; privé String tweetText; privé Date dateCreated; // getters en setters}

4.2. Tweeten en TweetensionalImpl

Dan, vergelijkbaar met de Gebruiker, maken we de Tweeten interface waarmee tweets kunnen worden opgehaald:

openbare interface Tweetbao {List fetchTweets (String e-mail); }

Evenzo zullen we het TweetensionalImpl klasse die de implementatie van de fetchTweets methode:

public class Tweet DaoImpl implementeert Tweet Dao {@Override public List fetchTweets (String e-mail) {List tweets = new ArrayList (); // roep Twitter API aan en bereid tweets voor om tweets terug te sturen; }}

Hier zullen we Twitter-API's aanroepen om alle tweets van een gebruiker op te halen met zijn e-mail.

In dit geval biedt een DAO dus een gegevenstoegangsmechanisme met behulp van API's van derden.

4.3. Verbeteren Gebruiker Domein

Laten we als laatste het UserSocialMedia subklasse van onze Gebruiker class om een ​​lijst bij te houden van de Tweet voorwerpen:

openbare klasse UserSocialMedia breidt User {privélijst tweets uit; // getters en setters}

Hier, onze UserSocialMedia class is een complex domein dat de eigenschappen van de Gebruiker domein ook.

4.4. UserRepositoryImpl

Nu gaan we onze UserRepositoryImpl klasse om een Gebruiker domeinobject samen met een lijst met tweets:

openbare klasse UserRepositoryImpl implementeert UserRepository {privé User DaoImpl userbaoImpl; privé Tweet DaoImpl tweetbaoImpl; @Override openbare gebruiker get (lange id) {UserSocialMedia gebruiker = (UserSocialMedia) user DaoImpl.read (id); Lijst tweets = tweetensionalImpl.fetchTweets (user.getEmail ()); user.setTweets (tweets); terugkeer gebruiker; }}

Hier de UserRepositoryImpl extraheert gebruikersgegevens met behulp van de GebruikersdateImpl en tweets van gebruikers met de TweetensionalImpl.

Vervolgens verzamelt het beide sets informatie en levert het een domeinobject van het UserSocialMedia klasse die handig is voor onze zakelijke use-case. Daarom een repository vertrouwt op DAO's voor toegang tot gegevens uit verschillende bronnen.

Op dezelfde manier kunnen we onze Gebruiker domein om een ​​lijst met Facebook-berichten bij te houden.

5. Vergelijking van de twee patronen

Nu we de nuances van de DAO- en Repository-patronen hebben gezien, zullen we hun verschillen samenvatten:

  • DAO is een abstractie van gegevenspersistentie. Een repository is echter een abstractie van een verzameling objecten
  • DAO is een concept op een lager niveau, dichter bij de opslagsystemen. Repository is echter een concept van een hoger niveau, dichter bij de Domain-objecten
  • DAO werkt als een gegevenstoewijzing / -toegangslaag, die lelijke zoekopdrachten verbergt. Een opslagplaats is echter een laag tussen domeinen en gegevenstoegangslagen, waardoor de complexiteit van het verzamelen van gegevens en het voorbereiden van een domeinobject wordt verborgen
  • DAO kan niet worden geïmplementeerd met behulp van een repository. Een repository kan echter een DAO gebruiken om toegang te krijgen tot onderliggende opslag

Als we een anemisch domein hebben, is de repository ook slechts een DAO.

Bovendien, het repository-patroon stimuleert een domeingestuurd ontwerp, waardoor ook niet-technische teamleden gemakkelijk de gegevensstructuur kunnen begrijpen.

6. Conclusie

In dit artikel hebben we de verschillen tussen DAO- en repository-patronen onderzocht.

Eerst hebben we een basisimplementatie van het DAO-patroon onderzocht. Toen zagen we een vergelijkbare implementatie met behulp van het Repository-patroon.

Als laatste hebben we gekeken naar een repository die gebruikmaakt van meerdere DAO's, waardoor de mogelijkheden van een domein worden vergroot om een ​​zakelijk gebruik op te lossen.

Daarom kunnen we concluderen dat het Repository-patroon een betere aanpak is wanneer een app verandert van datacentrisch naar bedrijfsgericht.

Zoals gewoonlijk zijn alle code-implementaties beschikbaar op GitHub.