Quelle est la différence entre les modèles DAO et de référentiel?

424

Quelle est la différence entre les modèles DAO (Data Access Objects) et les modèles de référentiel? Je développe une application utilisant Enterprise Java Beans (EJB3), Hibernate ORM comme infrastructure et Domain-Driven Design (DDD) et Test-Driven Development (TDD) comme techniques de conception.

Thurein
la source

Réponses:

472

DAOest une abstraction de la persistance des données .
Repositoryest l'abstraction d' une collection d'objets .

DAOserait considérée comme plus proche de la base de données, souvent centrée sur les tables.
Repositoryserait considéré comme plus proche du domaine, ne traitant que des racines agrégées.

Repositorypourrait être implémenté à l'aide DAOde, mais vous ne feriez pas le contraire.

De plus, a Repositoryest généralement une interface plus étroite. Il devrait être tout simplement une collection d'objets, avec Get(id), Find(ISpecification), Add(Entity).

Une méthode comme celle-ci Updateest appropriée sur un DAO, mais pas sur un Repository- lorsque vous utilisez un Repository, les modifications apportées aux entités sont généralement suivies par UnitOfWork distinct.

Il semble courant de voir des implémentations appelées un Repositoryqui sont vraiment plus un DAO, et donc je pense qu'il y a une certaine confusion sur la différence entre elles.

quentin-starin
la source
27
Eh bien, vous ne voudriez pas que votre classe DAO implémente littéralement votre IRepositoryinterface. Vous souhaitez que votre référentiel utilise les DAO dans sa mise en œuvre. N'oubliez pas qu'un DAO sera un objet par table, alors qu'un référentiel devra presque toujours utiliser plusieurs DAO pour construire une seule entité. Si vous constatez que ce n'est pas le cas, que votre référentiel et votre entité n'ont besoin d'accéder qu'à une seule table, vous créez probablement un domaine anémique.
quentin-starin
29
J'ai remarqué dans le monde .NET spécifiquement que le terme "référentiel" est utilisé pour désigner ce qui est essentiellement un DAO; "DAO" est plus un terme Java.
Wayne Molina
14
Les DAO @Thurein ne sont pas par table, le modèle ne fait qu'abstraire l'accès à vos données - vous pouvez l'implémenter comme vous le souhaitez (par table, ou par groupe ou modèles). La méthode recommandée consiste à toujours façonner vos DAO en fonction de votre modèle de domaine plutôt que de prendre en compte la persistance sous-jacente, car cela facilite / clarifie l'utilisation et vous donne un peu plus de flexibilité sur la façon dont vous le persistez (par exemple, imaginez que vous aurez besoin un DAO qui stocke vos données dans des fichiers XML ou les obtient à partir d'une file d'attente de messages plutôt qu'à partir d'une base de données ...).
Stef
21
@Stef, je ne suis pas d'accord. Un DAO renvoie des données par sa définition même (un objet d'accès aux données ). Un référentiel, par sa définition, renvoie des objets de domaine. Il devrait être évident que le référentiel utiliserait des DAO et non l'inverse, car dans la POO, nous composons des objets de domaine à partir d'un ou plusieurs objets de données, et non l'inverse.
Mihai Danila
6
Pourquoi un référentiel est-il un concept de "lecture seule" alors que DAO est "lecture et écriture"?
Dennis
121

OK, je pense que je peux mieux expliquer ce que j'ai mis dans les commentaires :). Donc, fondamentalement, vous pouvez voir les deux comme les mêmes, bien que DAO soit un modèle plus flexible que Repository. Si vous souhaitez utiliser les deux, vous utiliserez le référentiel dans vos DAO. Je vais vous expliquer chacun d'eux ci-dessous:

DÉPÔT:

Il s'agit d'un référentiel d'un type spécifique d'objets - il vous permet de rechercher un type spécifique d'objets ainsi que de les stocker. Habituellement, il ne traitera qu'un seul type d'objets. Par exemple AppleRepository, vous permettrait de faire AppleRepository.findAll(criteria)ou AppleRepository.save(juicyApple). Notez que le référentiel utilise des termes de modèle de domaine (pas des termes de base de données - rien lié à la façon dont les données sont conservées n'importe où).

Un référentiel stockera très probablement toutes les données dans la même table, alors que le modèle ne l'exige pas. Cependant, le fait qu'il ne gère qu'un seul type de données le rend logiquement connecté à une table principale (s'il est utilisé pour la persistance de la base de données).

DAO - objet d'accès aux données (en d'autres termes - objet utilisé pour accéder aux données)

Un DAO est une classe qui localise les données pour vous (il s'agit principalement d'un chercheur, mais il est couramment utilisé pour stocker également les données). Le modèle ne vous restreint pas pour stocker des données du même type, vous pouvez donc facilement avoir un DAO qui localise / stocke les objets associés.

Par exemple, vous pouvez facilement avoir UserDao qui expose des méthodes comme

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

Tous ceux-ci sont liés à l'utilisateur (et à la sécurité) et peuvent être spécifiés sous le même DAO. Ce n'est pas le cas pour le référentiel.

finalement

Notez que les deux modèles signifient vraiment la même chose (ils stockent des données et en retirent l'accès et ils sont tous deux exprimés plus près du modèle de domaine et ne contiennent pratiquement aucune référence de base de données), mais la façon dont ils sont utilisés peut être légèrement différente, DAO étant un peu plus flexible / générique, tandis que le référentiel est un peu plus spécifique et restrictif pour un type uniquement.

Stef
la source
Si je comprends bien, par exemple, j'ai quelque chose comme CarDescriptionça, par exemple language_idcomme clé étrangère - alors pour récupérer que je devrais faire quelque chose comme ça: CarRepository.getAll(new Criteria(carOwner.id, language.id));ce qui me donnerait toutes les voitures d'une langue dans une langue spécifique - est-ce la bonne façon de le faire ?
displayname
@StefanFalk, jetez un oeil à Spring Data, cela vous permet de faire des appels beaucoup plus agréables que cela. Par exemple, cela pourrait être écrit comme CarRepository.findByLanguageId(language.id)et vous n'auriez même pas besoin d'écrire le code, vous définissez simplement l'interface avec une méthode avec ce nom et Spring Data s'occupe de construire l'implémentation de classe par défaut pour vous. Des trucs assez soignés;)
Stef
2
La beauté de Spring Data est que vous n'avez pas réellement à écrire les requêtes, vous créez simplement une interface (comme celle de TodoRepository dans votre exemple, qui a la méthode findById). Et vous avez pratiquement terminé. Ce que fait Spring Data, c'est qu'il trouve toutes ces interfaces que vous avez créées qui étendent l'interface du référentiel et crée les classes pour vous. Vous ne verrez jamais ces classes et vous ne pourrez pas créer de nouvelles instances, mais vous n'en avez pas besoin car vous pouvez simplement câbler automatiquement l'interface et laisser Spring localiser cet objet de référentiel.
Stef
1
Enfin, vous n'avez pas à utiliser Spring Data, vous pouvez suivre l'ancienne méthode d'écriture des méthodes de requête vous-même (en utilisant l'API Criteria, etc.), mais vous rendriez votre vie un peu plus complexe ... Vous pourriez dire que vous auriez plus de flexibilité comme ça, mais ce n'est pas vrai non plus comme si vous voulez vraiment devenir fou avec vos requêtes, Spring Data vous permet deux façons de le faire: l'annotation @Query, ou si cela ne fonctionne pas, vous pouvez créer des référentiels personnalisés qui sont une extension qui vous donne la même puissance que si vous écriviez votre propre implémentation à partir de zéro.
Stef
2
"Racine agrégée" est un terme souvent lié au modèle de référentiel. Je ne sais pas comment vous utiliseriez cela avec votre définition d'un référentiel.
Christian Strempfer
90

DAO et le modèle de référentiel sont des moyens d'implémenter la couche d'accès aux données (DAL). Commençons donc par DAL, d'abord.

Les applications orientées objet qui accèdent à une base de données doivent avoir une logique pour gérer l'accès à la base de données. Afin de garder le code propre et modulaire, il est recommandé que la logique d'accès à la base de données soit isolée dans un module séparé. Dans l'architecture en couches, ce module est DAL.

Jusqu'à présent, nous n'avons pas parlé d'implémentation particulière: seulement un principe général qui place la logique d'accès à la base de données dans un module séparé.

Maintenant, comment pouvons-nous mettre en œuvre ce principe? Eh bien, une manière connue de l'implémenter, en particulier avec des frameworks comme Hibernate, est le modèle DAO.

Le modèle DAO est un moyen de générer DAL, où généralement, chaque entité de domaine a son propre DAO. Par exemple, Useret UserDao, Appointmentet AppointmentDao, etc. Un exemple de DAO avec Hibernate: http://gochev.blogspot.ca/2009/08/hibernate-generic-dao.html .

Alors, quel est le modèle de référentiel? Comme DAO, le modèle de référentiel est également un moyen d'atteindre DAL. Le point principal du modèle de référentiel est que, du point de vue client / utilisateur, il doit ressembler ou se comporter comme une collection. Ce que l'on entend par se comporter comme une collection, ce n'est pas qu'elle doive être instanciée comme Collection collection = new SomeCollection(). Au lieu de cela, cela signifie qu'il doit prendre en charge des opérations telles que l'ajout, la suppression, la conservation, etc. C'est l'essence même du modèle de référentiel.

En pratique, par exemple dans le cas de l'utilisation d'Hibernate, le modèle de référentiel est réalisé avec DAO. C'est une instance de DAL qui peut être à la fois une instance de modèle DAO et un modèle de référentiel.

Le modèle de référentiel n'est pas nécessairement quelque chose que l'on construit au-dessus de DAO (comme certains le suggèrent). Si les DAO sont conçus avec une interface qui prend en charge les opérations susmentionnées, il s'agit d'une instance de modèle de référentiel. Pensez-y, si les DAO fournissent déjà un ensemble d'opérations de type collection, alors quel est le besoin d'une couche supplémentaire par-dessus?

Nazar Merza
la source
5
"Si les DAO fournissent déjà un ensemble d'opérations de type collection, alors quel est le besoin d'une couche supplémentaire par-dessus?" Supposons que vous modélisez une animalerie et que vous avez une table 'PetType' avec différents animaux et leurs attributs (nom: "Chat", tapez: "Mammifère", etc.) référencés par une table 'Pet' des animaux de compagnie en béton que vous avoir dans la boutique (nom: "Katniss", race: "Calico", etc.). Si vous souhaitez ajouter un animal d'un type qui ne figure pas déjà dans la base de données, vous pouvez utiliser un référentiel pour regrouper les deux appels DAO distincts (l'un pour créer PetType et l'autre pour l'animal) dans une même méthode, en évitant le couplage dans les DAO
Matt
1
Superbe explication, monsieur!
Paul-Sebastian Manole
74

Franchement, cela ressemble à une distinction sémantique, pas à une distinction technique. L'expression Data Access Object ne fait pas du tout référence à une "base de données". Et, bien que vous puissiez le concevoir pour qu'il soit centré sur la base de données, je pense que la plupart des gens envisageraient de le faire comme une faille de conception.

Le but du DAO est de masquer les détails de mise en œuvre du mécanisme d'accès aux données. En quoi le modèle de référentiel est-il différent? Pour autant que je sache, ce n'est pas le cas. Dire un référentiel est différent d'un DAO parce que vous traitez / renvoyez une collection d'objets ne peut pas être correct; Les DAO peuvent également renvoyer des collections d'objets.

Tout ce que j'ai lu sur le modèle de référentiel semble reposer sur cette distinction: mauvaise conception DAO vs bonne conception DAO (alias modèle de conception de référentiel).

rakehell404
la source
5
oui, tout à fait d'accord, ils sont essentiellement les mêmes. DAO semble plus lié à DB, mais ce n'est pas le cas. Identique au référentiel, c'est juste une abstraction utilisée pour cacher où et comment se trouvent les données.
Stef
+1 Pour cette déclaration. Franchement, cela ressemble à une distinction sémantique, pas à une distinction technique. L'expression Data Access Object ne fait pas du tout référence à une "base de données".
Sudhakar Chavali
1
Le point lorsque l'on compare des référentiels et des collections n'est pas qu'ils traitent / retournent des collections d'objets, mais que les référentiels se comportent comme s'ils étaient eux-mêmes des collections. Par exemple, en Java, cela signifie qu'un référentiel n'a pas de méthode de mise à jour car lorsque vous modifiez un objet dans une collection, il est automatiquement mis à jour (car les collections Java stockent uniquement les références aux objets).
Christoph Böhme
17

Le référentiel est un terme plus abstrait orienté domaine qui fait partie de la conception pilotée par le domaine, il fait partie de la conception de votre domaine et un langage commun, DAO est une abstraction technique pour la technologie d'accès aux données, le référentiel ne concerne que la gestion des données existantes et des usines pour la création de Les données.

vérifiez ces liens:

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

Mohamed Abed
la source
6

La principale différence est qu'un référentiel gère l'accès aux racines d'agrégat dans un agrégat, tandis que DAO gère l'accès aux entités. Par conséquent, il est courant qu'un référentiel délègue la persistance réelle des racines agrégées à un DAO. De plus, comme la racine agrégée doit gérer l'accès des autres entités, il peut être nécessaire de déléguer cet accès à d'autres DAO.

pablochacine
la source
5

DAO fournit une abstraction sur la base de données / fichiers de données ou tout autre mécanisme de persistance afin que la couche de persistance puisse être manipulée sans connaître ses détails d'implémentation.

Alors que dans les classes de référentiel, plusieurs classes DAO peuvent être utilisées dans une seule méthode de référentiel pour effectuer une opération du «point de vue de l'application». Ainsi, au lieu d'utiliser plusieurs DAO sur la couche Domaine, utilisez le référentiel pour le faire. Le référentiel est une couche qui peut contenir une logique d'application comme: Si les données sont disponibles dans le cache en mémoire, récupérez-les dans le cache sinon, récupérez les données du réseau et stockez-les dans le cache en mémoire pour la prochaine récupération.

Rahul Rastogi
la source
3

Le référentiel n'est rien d'autre qu'un DAO bien conçu.

ORM sont centrés sur la table mais pas DAO.

Il n'est pas nécessaire d'utiliser plusieurs DAO dans le référentiel car DAO lui-même peut faire exactement la même chose avec les référentiels / entités ORM ou tout fournisseur DAL, peu importe où et comment une voiture est persistante 1 table, 2 tables, n tables, une demi-table, un service Web, une table et un service Web, etc. Les services utilisent plusieurs DAO / référentiels.

Mon propre DAO, disons que CarDao ne traite qu'avec Car DTO, je veux dire, ne prend que Car DTO en entrée et ne renvoie que les collections DTO voiture ou DTO voiture en sortie.

Donc, tout comme Repository, DAO est en fait un IoC, pour la logique métier, permettant aux interfaces de persistance de ne pas être intimidées par des stratégies de persistance ou des héritages. DAO encapsule la stratégie de persistance et fournit l'interface de persistance liée au domaine. Référentiel n'est qu'un autre mot pour ceux qui n'avaient pas compris ce qu'était réellement un DAO bien défini.

Cyril
la source
Tout d'abord "référentiels / entités ORM"? Vous voulez dire les entités ORM. Il n'existe pas de référentiel d'ORM. Deuxièmement, tous les ORM ne traitent généralement qu'avec des entités, c'est-à-dire. modèles de domaine. Les DAO traitent directement les tables et l'accès aux données abstraites. Ils rendent également des entités. Les référentiels sont l'abstraction la plus élevée, offrant une interface de collecte pour obtenir des entités. Un DAO peut être un référentiel, c'est-à-dire. en faisant abstraction du moteur de stockage réel, en lui offrant une interface et en offrant également une vue de collection des entités (cache). Un DAO peut utiliser un ORM pour s'interfacer avec la base de données et déléguer les opérations d'entité.
Paul-Sebastian Manole
3
D'accord avec @brokenthorn. Le point le plus crucial de son commentaire est "Les référentiels sont l'abstraction la plus élevée", et cette abstraction devient une nécessité lorsque vous souhaitez protéger votre code de domaine contre la technologie de base de données sous-jacente. Les concepts ORM / Adaptateur / Pilote DB ont tendance à s'infiltrer dans les DAO. Si vous avez une application qui prend en charge plusieurs technologies de base de données, ou si vous souhaitez que votre application ne soit pas verrouillée sur une base de données, l'utilisation de DAO directement à partir du modèle de domaine est un pas.
Subhash Bhushan
2

Essayez de savoir si DAO ou le modèle de référentiel s'applique le mieux à la situation suivante: imaginez que vous souhaitez fournir une API d'accès aux données uniforme pour un mécanisme persistant à divers types de sources de données telles que RDBMS, LDAP, OODB, référentiels XML et fichiers plats.

Consultez également les liens suivants, si vous êtes intéressé:

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
la source
0

dans une phrase très simple: la différence significative étant que les référentiels représentent des collections, tandis que les DAO sont plus proches de la base de données, étant souvent beaucoup plus centrés sur les tables.

Alireza Rahmani Khalili
la source
DAO peut aussi représenter des collections / objets ...
Yousha Aleayoub
0

Dans le framework Spring, il y a une annotation appelée le référentiel, et dans la description de cette annotation, il y a des informations utiles sur le référentiel, qui je pense qu'elles sont utiles pour cette discussion.

Indique qu'une classe annotée est un "référentiel", initialement défini par Domain-Driven Design (Evans, 2003) comme "un mécanisme d'encapsulation du stockage, de la récupération et du comportement de recherche qui émule une collection d'objets".

Les équipes qui implémentent des modèles Java EE traditionnels tels que "Data Access Object" peuvent également appliquer ce stéréotype aux classes DAO, mais il faut prendre soin de comprendre la distinction entre Data Access Object et les référentiels de style DDD avant de le faire. Cette annotation est un stéréotype à usage général et les équipes individuelles peuvent restreindre leur sémantique et utiliser le cas échéant.

Une classe ainsi annotée est éligible pour la traduction Spring DataAccessException lorsqu'elle est utilisée en conjonction avec un PersistenceExceptionTranslationPostProcessor. La classe annotée est également clarifiée quant à son rôle dans l'architecture globale de l'application à des fins d'outillage, d'aspects, etc.

Ali Yeganeh
la source