Qual è la differenza tra i modelli DAO e Repository?


424

Qual è la differenza tra i modelli Data Access Objects (DAO) e Repository? Sto sviluppando un'applicazione utilizzando Enterprise Java Beans (EJB3), Hibernate ORM come infrastruttura e Domain-Driven Design (DDD) e Test-Driven Development (TDD) come tecniche di progettazione.

Risposte:


472

DAOè un'astrazione della persistenza dei dati .
Repositoryè un'astrazione di una collezione di oggetti .

DAOsarebbe considerato più vicino al database, spesso incentrato sulla tabella.
Repositorysarebbe considerato più vicino al Dominio, trattando solo in Radici Aggregate.

Repositorypotrebbe essere implementato usando DAO"s", ma non faresti il ​​contrario.

Inoltre, a Repositoryè generalmente un'interfaccia più stretta. Dovrebbe essere semplicemente una collezione di oggetti, con un Get(id), Find(ISpecification), Add(Entity).

Un metodo simile Updateè appropriato su a DAO, ma non su Repository- quando si utilizza a Repository, le modifiche alle entità verrebbero generalmente monitorate da UnitOfWork separato.

Sembra comune vedere implementazioni chiamate a Repositoryche sono davvero più di a DAO, e quindi penso che ci sia un po 'di confusione sulla differenza tra loro.


27
Bene, non vorresti che la tua classe DAO implementasse letteralmente la tua IRepositoryinterfaccia. Vorresti che il tuo repository usasse i DAO nella sua implementazione. Ricorda, un DAO sarà un oggetto per tabella, mentre un repository dovrà quasi sempre usare più DAO per costruire una singola Entità. Se scopri che non è così, che il tuo Repository ed Entity devono solo accedere a una singola tabella, allora probabilmente stai costruendo un dominio anemico.
Quentin-starin il

29
Ho notato nel mondo .NET in particolare il termine "repository" è usato per riferirsi a ciò che è essenzialmente un DAO; "DAO" è più un termine Java.
Wayne Molina,

14
@Thurein I DAO non sono per tabella, il modello sta solo astraggendo l'accesso ai tuoi dati - puoi implementarlo come preferisci (per tabella, o per gruppo o modelli). Il modo consigliato è di modellare sempre i DAO in base al modello di dominio anziché tenere conto della persistenza sottostante in quanto rende più semplice / chiaro l'utilizzo e ti dà un po 'più di flessibilità su come lo perseveri (ad esempio immagina di averne bisogno un DAO che memorizza i tuoi dati in file XML o li ottiene da una coda di messaggi piuttosto che dal Database ...).
Stef

21
@Stef Non sono d'accordo. Un DAO restituisce i dati per definizione (un oggetto di accesso ai dati ). Un repository, per definizione, restituisce oggetti di dominio. Dovrebbe essere ragionevole pensare che il repository userebbe DAO e non viceversa, perché in OOP componiamo oggetti di dominio da uno o più oggetti di dati e non viceversa.
Mihai Danila,

6
Perché un repository è un concetto di "sola lettura" mentre DAO è "lettura e scrittura"?
Dennis

121

OK, penso di poter spiegare meglio cosa ho inserito nei commenti :). Quindi, fondamentalmente, puoi vedere entrambi uguali, sebbene DAO sia un modello più flessibile rispetto al repository. Se si desidera utilizzare entrambi, utilizzare il repository nei DAO. Spiegherò ciascuno di loro di seguito:

repository:

È un repository di un tipo specifico di oggetti: consente di cercare un tipo specifico di oggetti e di memorizzarli. Di solito gestirà SOLO un tipo di oggetti. Ad esempio AppleRepositoryti permetterebbe di fare AppleRepository.findAll(criteria)o AppleRepository.save(juicyApple). Si noti che il repository utilizza i termini del modello di dominio (non i termini DB, nulla correlato al modo in cui i dati vengono mantenuti ovunque).

Molto probabilmente un repository memorizzerà tutti i dati nella stessa tabella, mentre il modello non lo richiede. Il fatto che gestisca solo un tipo di dati lo rende logicamente connesso a una tabella principale (se utilizzata per la persistenza del DB).

DAO - oggetto di accesso ai dati (in altre parole - oggetto usato per accedere ai dati)

Un DAO è una classe che individua i dati per te (è principalmente un finder, ma è comunemente usato anche per archiviare i dati). Il modello non ti limita a memorizzare dati dello stesso tipo, quindi puoi facilmente avere un DAO che individua / memorizza oggetti correlati.

Ad esempio puoi facilmente avere UserDao che espone metodi come

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

Tutti questi sono correlati all'utente (e alla sicurezza) e possono essere specificati sotto lo stesso DAO. Questo non è il caso del repository.

Finalmente

Si noti che entrambi i modelli hanno davvero lo stesso significato (memorizzano i dati e astraggono l'accesso ad essi e sono entrambi espressi più vicini al modello di dominio e non contengono quasi alcun riferimento DB), ma il modo in cui vengono utilizzati può essere leggermente diverso, essendo DAO un po 'più flessibile / generico, mentre Repository è un po' più specifico e restrittivo solo per un tipo.


Se capisco bene, ad es. Ho qualcosa del genere, CarDescriptionad esempio, language_idcome chiave esterna - quindi per recuperare che dovrei fare qualcosa del genere: CarRepository.getAll(new Criteria(carOwner.id, language.id));che mi darebbe tutte le macchine di una lingua in una lingua specifica - è che il modo giusto di farlo ?
displayname

@StefanFalk, dai un'occhiata a Spring Data, ti permette di fare chiamate molto più belle di così. ad es. che potrebbe essere scritto come CarRepository.findByLanguageId(language.id)e non avresti nemmeno bisogno di scrivere il codice, devi solo definire l'interfaccia con un metodo con quel nome e Spring Data si occupa di costruire l'implementazione della classe predefinita per te. Roba piuttosto ordinata;)
Stef

2
Il bello di Spring Data è che in realtà non devi scrivere le query, devi solo creare un'interfaccia (come quella TodoRepository nel tuo esempio, che ha il metodo findById). E hai praticamente finito. Quello che poi fa Spring Data è, trova tutte queste interfacce che hai creato che estendono l'interfaccia del repository e crea le classi per te. Non vedrai mai quelle classi e non sarai in grado di creare nuove istanze, ma non è necessario in quanto puoi semplicemente autorizzare l'interfaccia e lasciare che Spring localizzi quell'oggetto repository.
Stef

1
Infine, non devi usare Spring Data, puoi andare da solo nel modo di scrivere i metodi di query (usando Criteria API ecc.), Ma renderebbe la tua vita un po 'più complessa ... Potresti dire che avresti una maggiore flessibilità come quella, ma non è vero neanche come se volessi davvero impazzire con le tue query, Spring Data ti offre due modi per farlo: l'annotazione @Query, o se non funziona, puoi crea repository personalizzati che sono un'estensione che ti dà la stessa potenza di se scrivi la tua implementazione da zero.
Stef

2
"Radice aggregata" è un termine spesso collegato al modello di repository. Non so come lo useresti con la tua definizione di repository.
Christian Strempfer,

90

DAO e modello di repository sono modi per implementare Data Access Layer (DAL). Quindi, iniziamo con DAL, prima.

Le applicazioni orientate agli oggetti che accedono a un database devono avere una logica per gestire l'accesso al database. Per mantenere il codice pulito e modulare, si consiglia di isolare la logica di accesso al database in un modulo separato. Nell'architettura a strati, questo modulo è DAL.

Finora non abbiamo parlato di un'implementazione particolare: solo un principio generale che mette la logica di accesso al database in un modulo separato.

Ora, come possiamo applicare questo principio? Bene, un modo noto per implementarlo, in particolare con framework come Hibernate, è il modello DAO.

Il modello DAO è un modo per generare DAL, dove in genere ogni entità di dominio ha il proprio DAO. Ad esempio, Usere UserDao, Appointmente AppointmentDao, ecc. Un esempio di DAO con Hibernate: http://gochev.blogspot.ca/2009/08/hibernate-generic-dao.html .

Allora qual è il modello di deposito? Come DAO, anche il modello di repository è un modo per raggiungere il DAL. Il punto principale nel modello di repository è che, dal punto di vista client / utente, dovrebbe apparire o comportarsi come una raccolta. Ciò che si intende comportandosi come una collezione non è che debba essere istanziato come Collection collection = new SomeCollection(). Invece, significa che dovrebbe supportare operazioni come aggiungere, rimuovere, contenere, ecc. Questa è l'essenza del modello di repository.

In pratica, ad esempio nel caso dell'utilizzo di Hibernate, il modello di repository viene realizzato con DAO. Questa è un'istanza di DAL può essere allo stesso tempo un'istanza del modello DAO e del modello del repository.

Il modello di repository non è necessariamente qualcosa che si basa su DAO (come alcuni potrebbero suggerire). Se i DAO sono progettati con un'interfaccia che supporta le operazioni sopra menzionate, si tratta di un'istanza del modello di repository. Pensaci, se i DAO forniscono già una serie di operazioni simili a raccolte, allora qual è la necessità di un ulteriore livello?


5
"Se i DAO forniscono già una serie di operazioni simili a raccolte, allora qual è la necessità di un livello aggiuntivo?" Supponiamo di modellare un negozio di animali e di avere una tabella "PetType" con diversi animali e i loro attributi (nome: "Gatto", tipo: "Mammifero", ecc.) A cui fa riferimento una tabella "Animale domestico" degli animali domestici in cemento che nel negozio (nome: "Katniss", razza: "Calico", ecc.). Se si desidera aggiungere un animale di un tipo non già presente nel database, è possibile utilizzare un repository per raggruppare le due chiamate DAO separate (una per creare PetType e l'altra per l'animale domestico) in un metodo, evitando l'accoppiamento in DAO
Matt

1
Superba spiegazione, signore!
Paul-Sebastian Manole,

74

Francamente, questo sembra una distinzione semantica, non una distinzione tecnica. La frase Data Access Object non si riferisce affatto a un "database". E, sebbene tu possa progettarlo come incentrato sul database, penso che la maggior parte delle persone considererebbe di farlo un difetto di progettazione.

Lo scopo del DAO è nascondere i dettagli di implementazione del meccanismo di accesso ai dati. In che modo differisce il modello di deposito? Per quanto ne so, non lo è. Dire che un repository è diverso da un DAO perché hai a che fare con / restituire una collezione di oggetti non può essere giusto; I DAO possono anche restituire raccolte di oggetti.

Tutto ciò che ho letto sul modello di repository sembra basarsi su questa distinzione: cattivo design DAO vs buon design DAO (noto anche come design pattern del repository).


5
sì, sono totalmente d'accordo, sono essenzialmente gli stessi. DAO sembra più legato al DB, ma non lo è. Come nel repository, è solo un'astrazione utilizzata per nascondere dove e come si trovano i dati.
Stef

+1 per questa affermazione. Francamente, questo sembra una distinzione semantica, non una distinzione tecnica. La frase Data Access Object non si riferisce affatto a un "database".
Sudhakar Chavali,

1
Il punto in cui si confrontano Repository e collezioni non è che hanno a che fare / ritorno collezioni di oggetti, ma che i repository si comportano come se sono raccolte stesse. Ad esempio, in Java ciò significa che un repository non ha un metodo di aggiornamento perché quando si modifica un oggetto in una raccolta, questo viene automaticamente aggiornato (poiché le raccolte Java memorizzano solo i riferimenti agli oggetti).
Christoph Böhme,

17

Repository è un termine più astratto orientato al dominio che fa parte del Domain Driven Design, fa parte del design del tuo dominio e di un linguaggio comune, DAO è un'astrazione tecnica per la tecnologia di accesso ai dati, il repository riguarda solo la gestione di dati e fabbriche esistenti per la creazione di dati.

controlla questi link:

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


6

La differenza fondamentale è che un repository gestisce l'accesso alle radici aggregate in un aggregato, mentre DAO gestisce l'accesso alle entità. Pertanto, è comune che un repository deleghi la persistenza effettiva delle radici aggregate a un DAO. Inoltre, poiché la radice aggregata deve gestire l'accesso delle altre entità, potrebbe essere necessario delegare questo accesso ad altri DAO.


5

DAO fornisce astrazione su file di database / dati o qualsiasi altro meccanismo di persistenza in modo che il livello di persistenza possa essere manipolato senza conoscerne i dettagli di implementazione.

Considerando che nelle classi Repository, più classi DAO possono essere utilizzate all'interno di un singolo metodo Repository per eseguire un'operazione dal "punto di vista dell'app". Quindi, invece di utilizzare più DAO a livello di dominio, utilizzare il repository per farlo. Il repository è un livello che può contenere una logica applicativa come: Se i dati sono disponibili nella cache in memoria, recuperarli dalla cache in caso contrario, recuperare i dati dalla rete e archiviarli nella cache in memoria per il successivo recupero.


3

Il repository non è altro che DAO ben progettato.

Gli ORM sono centrati sulla tabella ma non DAO.

Non è necessario utilizzare diversi DAO nel repository poiché DAO stesso può fare esattamente lo stesso con repository / entità ORM o qualsiasi provider DAL, indipendentemente da dove e come viene mantenuta un'auto 1 tabella, 2 tabelle, n tabelle, mezza tabella, un servizio web, una tabella e un servizio web ecc. I servizi utilizzano diversi DAO / repository.

Il mio DAO, diciamo che CarDao si occupa solo di Car DTO, intendo, accetta solo Car DTO in input e restituisce solo auto DTO o auto DTO in output.

Quindi, proprio come Repository, DAO è in realtà un IoC, per la logica aziendale, che consente alle interfacce di persistenza di non essere intimidite da strategie o lasciti di persistenza. DAO incapsula entrambi la strategia di persistenza e fornisce l'interfaccia di persistenza relativa a domaine. Repository è solo un'altra parola per coloro che non avevano capito cosa fosse effettivamente un DAO ben definito.


Prima di tutto "repository / entità ORM"? Intendi entità ORM. Non esiste un repository di ORM. Il secondo di tutti gli ORM di solito riguarda solo entità, ad es. modelli di dominio. I DAO gestiscono direttamente le tabelle e accedono ai dati astratti. Restituiscono anche entità. I repository sono la massima astrazione, offrendo un'interfaccia di raccolta per ottenere entità. Un DAO può essere un repository, cioè. astrarre l'effettivo motore di archiviazione, offrendone un'interfaccia e offrendo anche una vista raccolta di entità (cache). Un DAO può utilizzare un ORM per interfacciarsi con il database e delegare le operazioni delle entità.
Paul-Sebastian Manole,

3
Concordo con @brokenthorn. Il punto più cruciale nel suo commento è "I repository sono la massima astrazione" e questa astrazione diventa una necessità quando si desidera proteggere il proprio codice di dominio dalla tecnologia del database sottostante. I concetti di driver ORM / Adapter / DB tendono a trapelare nei DAO. Se si dispone di un'applicazione che supporta più di una tecnologia di database o se si desidera che l'app non sia bloccata su un database, l'utilizzo di DAO direttamente dal modello di dominio non è necessario.
Subhash Bhushan,

2

Prova a scoprire se DAO o il modello di repository sono più applicabili alla seguente situazione: Immagina di voler fornire un'API di accesso ai dati uniforme per un meccanismo persistente a vari tipi di origini dati come RDBMS, LDAP, OODB, repository XML e file flat.

Fare riferimento anche ai seguenti collegamenti, se interessati:

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

in una frase molto semplice: la differenza significativa è che i repository rappresentano raccolte, mentre i DAO sono più vicini al database, spesso essendo molto più incentrati sulle tabelle.


DAO può anche rappresentare collezioni / oggetti ...
Yousha Aleayoub,

0

Nel framework di primavera, c'è un'annotazione chiamata repository e nella descrizione di questa annotazione, ci sono informazioni utili sul repository, che ritengo sia utile per questa discussione.

Indica che una classe annotata è un "repository", originariamente definito da Domain-Driven Design (Evans, 2003) come "un meccanismo per incapsulare il comportamento di archiviazione, recupero e ricerca che emula una raccolta di oggetti".

I team che implementano i tradizionali schemi Java EE come "Data Access Object" possono anche applicare questo stereotipo alle classi DAO, sebbene prima di farlo si dovrebbe prestare attenzione a capire la distinzione tra Data Access Object e repository in stile DDD. Questa annotazione è uno stereotipo per tutti gli usi e i singoli team possono restringere la loro semantica e utilizzare come appropriato.

Una classe così annotata è idonea per la traduzione di Spring DataAccessException se utilizzata in combinazione con un PersistenceExceptionTranslationPostProcessor. La classe annotata viene inoltre chiarita in merito al suo ruolo nell'architettura generale dell'applicazione ai fini di strumenti, aspetti, ecc.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.