¿Cuál es la diferencia entre DAO y los patrones de repositorio?

424

¿Cuál es la diferencia entre los objetos de acceso a datos (DAO) y los patrones de repositorio? Estoy desarrollando una aplicación que usa Enterprise Java Beans (EJB3), Hibernate ORM como infraestructura y Domain-Driven Design (DDD) y Test-Driven Development (TDD) como técnicas de diseño.

Thurein
fuente

Respuestas:

472

DAOes una abstracción de persistencia de datos .
RepositoryEs una abstracción de una colección de objetos .

DAOse consideraría más cercano a la base de datos, a menudo centrada en la tabla.
Repositoryse consideraría más cercano al Dominio, que se ocupa solo de Raíces Agregadas.

Repositorypodría implementarse usando DAO's, pero no haría lo contrario.

Además, a Repositoryes generalmente una interfaz más estrecha. Debería ser simplemente una colección de objetos, con una Get(id), Find(ISpecification), Add(Entity).

Un método como Updatees apropiado en un DAO, pero no un Repository- cuando se usa un Repository, los cambios en las entidades generalmente serían rastreados por UnitOfWork por separado.

Parece común ver implementaciones llamadas a Repositoryque realmente son más de a DAO, y por lo tanto, creo que hay cierta confusión sobre la diferencia entre ellas.

quentin-starin
fuente
27
Bueno, no querrás que tu clase DAO implemente literalmente tu IRepositoryinterfaz. Desea que su repositorio use DAO en su implementación. Recuerde, un DAO será un objeto por tabla, mientras que un Repositorio casi siempre tendrá que usar múltiples DAO para construir una sola Entidad. Si considera que ese no es el caso, que su Repositorio y Entidad solo necesitan acceder a una sola tabla, entonces lo más probable es que esté creando un dominio anémico.
quentin-starin
29
He notado en el mundo .NET específicamente que el término "Repositorio" se usa para referirse a lo que es esencialmente un DAO; "DAO" es más un término de Java.
Wayne Molina
14
Los DAO-s de @Thurein no son por tabla, el patrón solo está abstrayendo el acceso a sus datos; puede implementarlo como desee (por tabla, por grupo o modelos). La forma recomendada es siempre dar forma a sus DAO en función de su modelo de dominio en lugar de tener en cuenta la persistencia subyacente, ya que eso hace que sea más fácil / más claro de usar y le brinda un poco más de flexibilidad sobre cómo lo persiste (por ejemplo, imagine que necesitará un DAO que almacena sus datos en archivos XML o los obtiene de una cola de mensajes en lugar de una Base de datos ...).
Stef
21
@ Stef no estoy de acuerdo. Un DAO devuelve datos por su propia definición (un objeto de acceso a datos ). Un repositorio, por su definición, devuelve objetos de dominio. Debería ser lógico pensar que el repositorio usaría DAO y no al revés, porque en OOP componimos objetos de dominio a partir de uno o más objetos de datos, y no al revés.
Mihai Danila
66
¿Por qué un repositorio es un concepto de "solo lectura" mientras que DAO es "lectura y escritura"?
Dennis
121

OK, creo que puedo explicar mejor lo que he puesto en los comentarios :). Entonces, básicamente, puedes ver a ambos como iguales, aunque DAO es un patrón más flexible que Repository. Si desea usar ambos, usaría el Repositorio en sus DAO-s. Explicaré cada uno de ellos a continuación:

REPOSITORIO:

Es un repositorio de un tipo específico de objetos: le permite buscar un tipo específico de objetos, así como almacenarlos. Por lo general, SOLO manejará un tipo de objetos. Por ejemplo AppleRepository, te permitiría hacer AppleRepository.findAll(criteria)o AppleRepository.save(juicyApple). Tenga en cuenta que el Repositorio usa términos del Modelo de dominio (no términos de base de datos, nada relacionado con la forma en que los datos se conservan en cualquier lugar).

Lo más probable es que un repositorio almacene todos los datos en la misma tabla, mientras que el patrón no lo requiere. Sin embargo, el hecho de que solo maneja un tipo de datos lo hace lógicamente conectado a una tabla principal (si se usa para la persistencia de la base de datos).

DAO: objeto de acceso a datos (en otras palabras, objeto utilizado para acceder a datos)

Un DAO es una clase que localiza datos por usted (es principalmente un buscador, pero se usa comúnmente para almacenar también los datos). El patrón no lo restringe para almacenar datos del mismo tipo, por lo que puede tener fácilmente un DAO que localice / almacene objetos relacionados.

Por ejemplo, puede tener fácilmente UserDao que expone métodos como

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

Todos estos están relacionados con el Usuario (y la seguridad) y se pueden especificar bajo el mismo DAO. Este no es el caso del repositorio.

Finalmente

Tenga en cuenta que ambos patrones realmente significan lo mismo (almacenan datos y abstraen el acceso a ellos y ambos se expresan más cerca del modelo de dominio y casi no contienen ninguna referencia DB), pero la forma en que se usan puede ser ligeramente diferente, ya que DAO un poco más flexible / genérico, mientras que Repository es un poco más específico y restrictivo solo para un tipo.

Stef
fuente
Si lo entiendo bien, por ejemplo, tengo algo como CarDescriptioneso, por ejemplo, language_idcomo clave foránea, entonces para recuperar que debería hacer algo como esto: CarRepository.getAll(new Criteria(carOwner.id, language.id));lo que me daría todos los automóviles de un idioma en un idioma específico, es esa la forma correcta de hacerlo ?
mostrar
@StefanFalk, eche un vistazo a Spring Data, le permite hacer llamadas mucho más agradables que eso. por ejemplo, podría escribirse así CarRepository.findByLanguageId(language.id)y ni siquiera necesitaría escribir el código, simplemente define la interfaz con un método con ese nombre y Spring Data se encarga de construir la implementación de clase predeterminada para usted. Cosas bonitas;)
Stef
2
La belleza de Spring Data es que en realidad no tiene que escribir las consultas, simplemente crea una interfaz (como ese TodoRepository en su ejemplo, que tiene el método findById). Y prácticamente has terminado. Lo que hace Spring Data es encontrar todas estas interfaces que ha creado que amplían la interfaz del Repositorio y crea las clases por usted. Nunca verá esas clases y no podrá crear nuevas instancias, pero no es necesario, ya que solo puede conectar automáticamente la interfaz y dejar que Spring localice ese objeto de repositorio.
Stef
1
Finalmente, no tiene que usar Spring Data, puede seguir la antigua forma de escribir los métodos de consulta usted mismo (usando Criteria API, etc.), pero simplemente haría su vida un poco más compleja ... Podría decir que tendrías más flexibilidad así, pero eso tampoco es cierto, ya que si realmente quieres volverte loco con tus consultas, Spring Data te permite dos formas de hacerlo: la anotación @Query, o si eso no funciona, puedes cree repositorios personalizados que son una extensión que le da el mismo poder que si escribiera su propia implementación desde cero.
Stef
2
"Raíz agregada" es un término a menudo conectado al patrón de repositorio. No sé cómo usarías eso con tu definición de repositorio.
Christian Strempfer
90

DAO y el patrón de repositorio son formas de implementar Data Access Layer (DAL). Entonces, comencemos con DAL, primero.

Las aplicaciones orientadas a objetos que acceden a una base de datos, deben tener cierta lógica para manejar el acceso a la base de datos. Para mantener el código limpio y modular, se recomienda que la lógica de acceso a la base de datos se aísle en un módulo separado. En la arquitectura en capas, este módulo es DAL.

Hasta ahora, no hemos hablado de ninguna implementación en particular: solo un principio general que pone la lógica de acceso a la base de datos en un módulo separado.

Ahora, ¿cómo podemos implementar este principio? Bueno, una forma conocida de implementar esto, en particular con marcos como Hibernate, es el patrón DAO.

El patrón DAO es una forma de generar DAL, donde típicamente, cada entidad de dominio tiene su propio DAO. Por ejemplo, Usery UserDao, Appointmenty AppointmentDao, etc. Un ejemplo de DAO con Hibernate: http://gochev.blogspot.ca/2009/08/hibernate-generic-dao.html .

Entonces, ¿qué es el patrón de repositorio? Al igual que DAO, el patrón de repositorio también es una forma de lograr DAL. El punto principal en el patrón de repositorio es que, desde la perspectiva del cliente / usuario, debe verse o comportarse como una colección. Lo que significa comportarse como una colección no es que tenga que ser instanciado como Collection collection = new SomeCollection(). En cambio, significa que debe admitir operaciones como agregar, eliminar, contiene, etc. Esta es la esencia del patrón de repositorio.

En la práctica, por ejemplo, en el caso de utilizar Hibernate, el patrón de repositorio se realiza con DAO. Esa es una instancia de DAL puede ser a la vez una instancia del patrón DAO y el patrón de repositorio.

El patrón de repositorio no es necesariamente algo que uno construye sobre DAO (como algunos pueden sugerir). Si los DAO están diseñados con una interfaz que admite las operaciones mencionadas anteriormente, entonces es una instancia del patrón de Repositorio. Piénselo, si los DAO ya proporcionan un conjunto de operaciones tipo colección, ¿cuál es la necesidad de una capa adicional encima?

Nazar Merza
fuente
55
"Si los DAO ya proporcionan un conjunto de operaciones de colección, entonces, ¿cuál es la necesidad de una capa adicional encima?" Supongamos que está modelando una tienda de mascotas y tiene una tabla 'PetType' con diferentes animales y sus atributos (nombre: "Gato", tipo: "Mamífero", etc.) referenciada por una tabla 'Mascota' de las mascotas concretas que usted tener en la tienda (nombre: "Katniss", raza: "Calico", etc.). Si desea agregar un animal de un tipo que aún no está en la base de datos, puede usar un repositorio para agrupar las dos llamadas DAO separadas (una para crear PetType y la otra para la mascota) en un método, evitando el acoplamiento en DAOs
Matt
1
¡Excelente explicación, señor!
Paul-Sebastian Manole
74

Francamente, esto parece una distinción semántica, no una distinción técnica. La frase Objeto de acceso a datos no se refiere a una "base de datos" en absoluto. Y, aunque podría diseñarlo para que se centre en la base de datos, creo que la mayoría de la gente consideraría hacerlo como una falla de diseño.

El propósito del DAO es ocultar los detalles de implementación del mecanismo de acceso a datos. ¿Cómo es diferente el patrón del repositorio? Por lo que puedo decir, no lo es. Decir que un repositorio es diferente a un DAO porque estás tratando / devuelve una colección de objetos no puede ser correcto; Los DAO también pueden devolver colecciones de objetos.

Todo lo que he leído sobre el patrón de repositorio parece basarse en esta distinción: diseño DAO malo versus diseño DAO bueno (también conocido como patrón de diseño de repositorio).

rakehell404
fuente
55
sí, totalmente de acuerdo, son esencialmente lo mismo. DAO suena más relacionado con DB, pero no lo es. Igual que el repositorio, es solo una abstracción utilizada para ocultar dónde y cómo se ubican los datos.
Stef
+1 para esta declaración. Francamente, esto parece una distinción semántica, no una distinción técnica. La frase Objeto de acceso a datos no se refiere a una "base de datos" en absoluto.
Sudhakar Chavali
1
El punto al comparar los repositorios y colecciones no es que están tratando / regresar colecciones de objetos, pero que los repositorios se comportan como si son colecciones mismas. Por ejemplo, en Java eso significa que un Repositorio no tiene un método de actualización porque cuando modifica un objeto en una colección se actualiza automáticamente (porque las colecciones Java solo almacenan referencias a objetos).
Christoph Böhme
17

El repositorio es un término más abstracto orientado al dominio que forma parte del diseño dirigido por el dominio, es parte del diseño de su dominio y un lenguaje común, DAO es una abstracción técnica para la tecnología de acceso a datos, el repositorio se preocupa solo por la administración de datos existentes y las fábricas para la creación de datos.

revisa estos enlaces:

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

Mohamed Abed
fuente
6

La diferencia clave es que un repositorio maneja el acceso a las raíces agregadas en un agregado, mientras que DAO maneja el acceso a las entidades. Por lo tanto, es común que un repositorio delegue la persistencia real de las raíces agregadas a un DAO. Además, como la raíz agregada debe manejar el acceso de las otras entidades, es posible que deba delegar este acceso a otros DAO.

pablochacina
fuente
5

DAO proporciona abstracción en archivos de bases de datos / datos o cualquier otro mecanismo de persistencia para que la capa de persistencia pueda ser manipulada sin conocer los detalles de su implementación.

Mientras que en las clases de repositorio, se pueden usar múltiples clases DAO dentro de un único método de repositorio para realizar una operación desde la "perspectiva de la aplicación". Entonces, en lugar de usar múltiples DAO en la capa de dominio, use el repositorio para hacerlo. El repositorio es una capa que puede contener cierta lógica de aplicación como: Si los datos están disponibles en la memoria caché en memoria, recójalo de la memoria caché; de lo contrario, recupere los datos de la red y almacénelos en la memoria caché en memoria para la próxima recuperación.

Rahul Rastogi
fuente
3

El repositorio no es más que DAO bien diseñado.

ORM se centra en la tabla pero no DAO.

No es necesario usar varios DAO en el repositorio ya que DAO puede hacer exactamente lo mismo con los repositorios / entidades ORM o cualquier proveedor de DAL, sin importar dónde y cómo se conserve un automóvil 1 tabla, 2 tablas, n tablas, media tabla, un servicio web, una tabla y un servicio web, etc. Los servicios utilizan varios DAO / repositorios.

Mi propio DAO, digamos que CarDao solo trata con Car DTO, es decir, solo toma Car DTO como entrada y solo devuelve colecciones de DTO de coche o DTO de coche en salida.

Entonces, al igual que Repository, DAO en realidad es un IoC, para la lógica de negocios, que permite que las interfaces de persistencia no se dejen intimidar por estrategias o legados de persistencia. DAO encapsula la estrategia de persistencia y proporciona la interfaz de persistencia relacionada con el dominio. El repositorio es solo otra palabra para aquellos que no han entendido lo que realmente era un DAO bien definido.

Cirilo
fuente
En primer lugar, "repositorios / entidades ORM"? Te refieres a las entidades ORM. No existe un repositorio de ORM. En segundo lugar, los ORM generalmente tratan solo con entidades, es decir. Modelos de dominio. Los DAO manejan tablas directamente y acceden a datos abstractos. También devuelven entidades. Los repositorios son la mayor abstracción, ya que ofrecen una interfaz de recopilación para obtener entidades. Un DAO puede ser un repositorio, es decir. abstraer el motor de almacenamiento real, ofrecerle una interfaz y también una vista de recopilación de entidades (caché). Un DAO puede usar un ORM para interactuar con la base de datos y delegar operaciones de entidad.
Paul-Sebastian Manole
3
De acuerdo con @brokenthorn. El punto más crucial en su comentario es "Los repositorios son la abstracción más alta", y esta abstracción se convierte en una necesidad cuando desea proteger su código de dominio de la tecnología de base de datos subyacente. Los conceptos de ORM / Adaptador / DB Driver tienden a filtrarse en DAO. Si tiene una aplicación que admite más de una tecnología de base de datos, o si desea que su aplicación no esté bloqueada en una base de datos, no se puede usar DAO directamente desde el modelo de dominio.
Subhash Bhushan
2

Intente averiguar si DAO o el patrón de repositorio es más aplicable a la siguiente situación: imagine que le gustaría proporcionar una API de acceso a datos uniforme para un mecanismo persistente a varios tipos de fuentes de datos como RDBMS, LDAP, OODB, repositorios XML y archivos planos.

Consulte también los siguientes enlaces, si está interesado:

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

en una oración muy simple: la diferencia significativa es que los repositorios representan colecciones, mientras que los DAO están más cerca de la base de datos, a menudo mucho más centrados en la tabla.

Alireza Rahmani Khalili
fuente
DAO también puede representar colecciones / objetos ...
Yousha Aleayoub
0

En el marco de primavera, hay una anotación llamada repositorio, y en la descripción de esta anotación, hay información útil sobre el repositorio, que creo que es útil para esta discusión.

Indica que una clase anotada es un "Repositorio", originalmente definido por Domain-Driven Design (Evans, 2003) como "un mecanismo para encapsular el almacenamiento, la recuperación y el comportamiento de búsqueda que emula una colección de objetos".

Los equipos que implementan patrones tradicionales de Java EE como el "Objeto de acceso a datos" también pueden aplicar este estereotipo a las clases DAO, aunque se debe tener cuidado de comprender la distinción entre el Objeto de acceso a datos y los repositorios de estilo DDD antes de hacerlo. Esta anotación es un estereotipo de propósito general y los equipos individuales pueden reducir su semántica y usarla según corresponda.

Una clase así anotada es elegible para la traducción Spring DataAccessException cuando se usa junto con un PersistenceExceptionTranslationPostProcessor. La clase anotada también se aclara en cuanto a su papel en la arquitectura general de la aplicación con el propósito de herramientas, aspectos, etc.

Ali Yeganeh
fuente