Qual é a diferença entre os padrões DAO e Repositório?

423

Qual é a diferença entre os padrões Data Access Objects (DAO) e Repository? Estou desenvolvendo um aplicativo usando Enterprise Java Beans (EJB3), Hibernate ORM como infraestrutura e Design Orientado a Domínio (DDD) e Desenvolvimento Orientado a Testes (TDD) como técnicas de design.

Thurein
fonte

Respostas:

472

DAOé uma abstração da persistência de dados .
Repositoryé uma abstração de uma coleção de objetos .

DAOseria considerado mais próximo do banco de dados, geralmente centrado na tabela.
Repositoryseria considerado mais próximo do domínio, lidando apenas com raízes agregadas.

Repositorypoderia ser implementado usando DAO's, mas você não faria o contrário.

Além disso, a Repositorygeralmente é uma interface mais estreita. Deve ser simplesmente uma coleção de objetos, com Get(id), Find(ISpecification), Add(Entity).

Um método como Updateé apropriado em uma DAO, mas não em uma Repository- ao usar a Repository, as alterações nas entidades geralmente seriam rastreadas por UnitOfWork separado.

Parece comum ver implementações chamadas a Repositoryque são realmente mais a DAO, e, portanto, acho que há alguma confusão sobre a diferença entre elas.

quentin-starin
fonte
27
Bem, você não gostaria que sua classe DAO implementasse literalmente sua IRepositoryinterface. Você deseja que seu repositório use DAOs em sua implementação. Lembre-se, um DAO será um objeto por tabela, enquanto um Repositório quase sempre precisará usar vários DAOs para criar uma única Entidade. Se você achar que não é esse o caso, que seu Repositório e Entidade precisam acessar apenas uma única tabela, provavelmente você está criando um domínio anêmico.
você
29
Notei no mundo .NET especificamente que o termo "Repositório" é usado para se referir ao que é essencialmente um DAO; "DAO" é mais um termo Java.
Wayne Molina
14
@Thurein DAO-s não são por tabela, o padrão está apenas abstraindo o acesso aos seus dados - você pode implementar o que quiser (por tabela, por grupo ou modelos). A maneira recomendada é sempre modelar seus DAOs com base no modelo de domínio, em vez de levar em consideração a persistência subjacente, pois isso facilita / torna mais claro o uso e oferece um pouco mais de flexibilidade em como você os persiste (por exemplo, imagine que você precisará um DAO que armazena seus dados em arquivos XML ou os obtém de uma fila de mensagens e não do banco de dados ...).
Stef
21
@ Stef eu discordo. Um DAO retorna dados por sua própria definição (um objeto de acesso a dados ). Um repositório, por sua definição, retorna objetos de domínio. Deveria ser lógico que o repositório usaria DAOs e não o contrário, porque no OOP compomos objetos de domínio de um ou mais objetos de dados, e não o contrário.
21313 Mihai Danila
6
Por que um Repositório é um conceito "Somente Leitura" enquanto o DAO é "Leitura e Gravação"?
Dennis
121

OK, acho que posso explicar melhor o que coloquei nos comentários :). Portanto, basicamente, você pode ver os dois iguais, embora o DAO seja um padrão mais flexível que o Repositório. Se você quiser usar os dois, use o Repositório em seus DAO-s. Vou explicar cada um deles abaixo:

REPOSITÓRIO:

É um repositório de um tipo específico de objetos - permite pesquisar um tipo específico de objetos e armazená-los. Normalmente, ele só lida com um tipo de objeto. Por exemplo AppleRepository, permitiria que você faça AppleRepository.findAll(criteria)ou AppleRepository.save(juicyApple). Observe que o Repositório está usando termos do Modelo de Domínio (não termos do banco de dados - nada relacionado a como os dados são mantidos em qualquer lugar).

Um repositório provavelmente armazenará todos os dados na mesma tabela, enquanto o padrão não exige isso. O fato de ele manipular apenas um tipo de dados, porém, o faz logicamente conectado a uma tabela principal (se usada para persistência do banco de dados).

DAO - objeto de acesso a dados (em outras palavras - objeto usado para acessar dados)

Um DAO é uma classe que localiza dados para você (é principalmente um localizador, mas é comumente usado para também armazenar os dados). O padrão não restringe o armazenamento de dados do mesmo tipo, portanto, você pode facilmente ter um DAO que localiza / armazena objetos relacionados.

Por exemplo, você pode facilmente ter o UserDao que expõe métodos como

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

Todos esses estão relacionados ao Usuário (e segurança) e podem ser especificados no mesmo DAO. Este não é o caso do Repositório.

Finalmente

Observe que os dois padrões realmente significam o mesmo (eles armazenam dados e abstraem o acesso a eles, e ambos são expressos mais perto do modelo de domínio e quase não contêm nenhuma referência ao banco de dados), mas a maneira como são usados ​​pode ser um pouco diferente, sendo o DAO um pouco mais flexível / genérico, enquanto o Repositório é um pouco mais específico e restritivo apenas a um tipo.

Stef
fonte
Se eu acertar, por exemplo, eu tenho algo parecido CarDescriptioncom, por exemplo, language_idcomo chave estrangeira - então, para recuperar que devo fazer algo assim: o CarRepository.getAll(new Criteria(carOwner.id, language.id));que me daria todos os carros de um idioma em um idioma específico - é o caminho certo para fazê-lo ?
displayname
@StefanFalk, dê uma olhada no Spring Data, ele permite que você faça chamadas muito melhores do que isso. por exemplo, isso pode ser escrito CarRepository.findByLanguageId(language.id)e você nem precisa escrever o código, basta definir a interface com um método com esse nome e o Spring Data cuida da criação da implementação de classe padrão para você. Coisas muito legais;) #
7285 Stef
2
A vantagem do Spring Data é que você não precisa escrever as consultas, basta criar uma interface (como o TodoRepository no seu exemplo, que possui o método findById). E você está praticamente pronto. O que o Spring Data faz é encontrar todas essas interfaces que você criou, que estendem a interface do Repositório e criam as classes para você. Você nunca verá essas classes e não poderá criar novas instâncias, mas não precisa, pois pode conectar a interface automaticamente e deixar o Spring localizar esse objeto de repositório.
Stef
1
Por fim, você não precisa usar o Spring Data, pode seguir o método antigo de escrever os métodos de consulta (usando a API Criteria etc.), mas apenas tornaria sua vida um pouco mais complexa ... Você pode dizer que você teria mais flexibilidade assim, mas isso não é verdade, como se você realmente quisesse enlouquecer com suas consultas, o Spring Data permite duas maneiras de fazer isso: a anotação @Query ou, se isso não funcionar, você pode crie repositórios personalizados que são uma extensão que oferece o mesmo poder que se você escrevesse sua própria implementação do zero.
585 Stef Stef
2
"Raiz agregada" é um termo geralmente conectado ao padrão do repositório. Não sei como você usaria isso com sua definição de repositório.
Christian Strempfer
90

O DAO e o padrão do repositório são formas de implementar o Data Access Layer (DAL). Então, vamos começar com o DAL, primeiro.

Os aplicativos orientados a objetos que acessam um banco de dados devem ter alguma lógica para lidar com o acesso ao banco de dados. Para manter o código limpo e modular, recomenda-se que a lógica de acesso ao banco de dados seja isolada em um módulo separado. Na arquitetura em camadas, este módulo é DAL.

Até o momento, não falamos sobre nenhuma implementação específica: apenas um princípio geral que coloca a lógica de acesso ao banco de dados em um módulo separado.

Agora, como podemos implementar esse princípio? Bem, uma maneira conhecida de implementar isso, em particular com estruturas como o Hibernate, é o padrão DAO.

O padrão DAO é uma maneira de gerar DAL, onde normalmente, cada entidade de domínio tem seu próprio DAO. Por exemplo, Usere UserDao,Appointment e AppointmentDao, etc. Um exemplo de DAO com Hibernate: http://gochev.blogspot.ca/2009/08/hibernate-generic-dao.html .

Então, o que é padrão de repositório? Como o DAO, o padrão do repositório também é uma maneira de obter o DAL. O ponto principal no padrão de repositório é que, da perspectiva do cliente / usuário, ele deve parecer ou se comportar como uma coleção. O que se entende por se comportar como uma coleção não é que ela precise ser instanciada Collection collection = new SomeCollection(). Em vez disso, significa que ele deve oferecer suporte a operações como adicionar, remover, conter etc. Essa é a essência do padrão do Repositório.

Na prática, por exemplo, no caso de usar o Hibernate, o padrão do Repositório é realizado com o DAO. Essa é uma instância do DAL e pode ser ao mesmo tempo uma instância do padrão DAO e do padrão Repository.

O padrão de repositório não é necessariamente algo que se constrói sobre o DAO (como alguns podem sugerir). Se os DAOs forem projetados com uma interface que suporte as operações mencionadas acima, será uma instância do padrão de Repositório. Pense nisso: se os DAOs já fornecem um conjunto de operações semelhantes a coleções, então qual é a necessidade de uma camada extra sobre ela?

Nazar Merza
fonte
5
"Se os DAOs já fornecem um conjunto de operações semelhantes a coleções, então qual é a necessidade de uma camada extra sobre ela?" Suponha que você esteja modelando uma pet shop e tenha uma tabela 'PetType' com diferentes animais e seus atributos (nome: "Gato", tipo: "Mamífero" etc.) referenciados pela tabela 'Pet' dos animais de estimação de concreto que você tem na loja (nome: "Katniss", raça: "Chita", etc.). Se você quiser adicionar um animal de um tipo que ainda não esteja no banco de dados, poderá usar um repositório para agrupar as duas chamadas DAO separadas (uma para criar PetType e outra para o Pet) em um método, evitando o acoplamento em DAOs
Matt
1
Explicação soberba, senhor!
Paul-Sebastian Manole 10/09
74

Francamente, isso parece uma distinção semântica, não uma distinção técnica. A frase Objeto de Acesso a Dados não se refere a um "banco de dados". E, embora você possa projetá-lo para ser centrado no banco de dados, acho que a maioria das pessoas consideraria isso uma falha de design.

O objetivo do DAO é ocultar os detalhes de implementação do mecanismo de acesso a dados. Como o padrão do Repositório é diferente? Tanto quanto eu posso dizer, não é. Dizer um Repositório é diferente de um DAO porque você está lidando com / retorna uma coleção de objetos não pode estar certo; Os DAOs também podem retornar coleções de objetos.

Tudo o que li sobre o padrão de repositório parece depender dessa distinção: design ruim do DAO versus bom design do DAO (também conhecido como padrão de design do repositório).

rakehell404
fonte
5
sim, concordo totalmente, eles são essencialmente os mesmos. O DAO parece mais relacionado ao banco de dados, mas não é. Assim como o Repositório, é apenas uma abstração usada para ocultar onde e como os dados estão localizados.
Stef
+1 para esta declaração. Francamente, isso parece uma distinção semântica, não uma distinção técnica. A frase Objeto de Acesso a Dados não se refere a um "banco de dados".
Sudhakar Chavali
1
O ponto ao comparar Repositórios e coleções não é que eles estão lidando / retornar coleções de objetos, mas que os repositórios se comportam como se eles são próprias coleções. Por exemplo, em Java, isso significa que um Repositório não possui um método de atualização porque, quando você modifica um objeto em uma coleção, ele é atualizado automaticamente (porque as coleções Java armazenam apenas referências a objetos).
Christoph Böhme 17/04
17

Repositório é um termo mais abstrato orientado ao domínio que faz parte do Design Orientado a Domínio, faz parte do design de domínio e é uma linguagem comum; o DAO é uma abstração técnica para a tecnologia de acesso a dados; o repositório se preocupa apenas com o gerenciamento de dados e fábricas existentes para a criação de dados.

verifique estes links:

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

Mohamed Abed
fonte
6

A principal diferença é que um repositório lida com o acesso às raízes agregadas de forma agregada, enquanto o DAO lida com o acesso às entidades. Portanto, é comum que um repositório delegue a persistência real das raízes agregadas a um DAO. Além disso, como a raiz agregada deve manipular o acesso de outras entidades, pode ser necessário delegar esse acesso a outros DAOs.

pablochacin
fonte
5

O DAO fornece abstração em arquivos de banco de dados / dados ou qualquer outro mecanismo de persistência para que a camada de persistência possa ser manipulada sem conhecer os detalhes da implementação.

Enquanto nas classes Repository, várias classes DAO podem ser usadas dentro de um único método Repository para executar uma operação da "perspectiva do aplicativo". Portanto, em vez de usar vários DAO na camada Domínio, use o repositório para fazer isso. Repositório é uma camada que pode conter alguma lógica de aplicativo como: Se os dados estiverem disponíveis no cache da memória, busque-os no cache, caso contrário, busque dados da rede e armazene-os no cache da memória para recuperação na próxima vez.

Rahul Rastogi
fonte
3

O repositório nada mais é que um DAO bem projetado.

O ORM é centralizado na tabela, mas não o DAO.

Não há necessidade de usar vários DAO no repositório, pois o DAO em si pode fazer exatamente o mesmo com repositórios / entidades ORM ou qualquer provedor DAL, não importa onde e como um carro seja persistido 1 tabela, 2 tabelas, n tabelas, meia tabela, uma serviço da web, uma tabela e um serviço da web etc. Os serviços usam vários DAO / repositórios.

Meu próprio DAO, digamos que o CarDao lide apenas com o DTO do carro, quero dizer, apenas leve o DTO do carro na entrada e retorne apenas as coleções de DTO do carro ou DTO do carro na saída.

Portanto, assim como o Repositório, o DAO na verdade é uma IoC, para a lógica de negócios, permitindo que as interfaces de persitência não sejam intimidadas por estratégias ou legados de persitência. O DAO encapsula a estratégia de persistência e fornece a interface de persistência relacionada ao domínio. Repositório é apenas mais uma palavra para aqueles que não entenderam o que era realmente um DAO bem definido.

Cyril
fonte
Primeiro de tudo "repositórios / entidades ORM"? Você quer dizer entidades ORM. Não existe um repositório de ORMs. Segundo de todos os ORMs geralmente lidam apenas com entidades, ou seja. modelos de domínio. Os DAOs lidam com tabelas diretamente e abstraem o acesso a dados. Eles retornam entidades também. Repositórios são a abstração mais alta, oferecendo uma interface de coleta para obter entidades. Um DAO pode ser um repositório, ie. abstraindo o mecanismo de armazenamento real, oferecendo uma interface a ele e também oferecendo uma exibição de coleção de entidades (cache). Um DAO pode usar um ORM para fazer interface com o banco de dados e delegar operações da entidade.
Paul-Sebastian Manole 17/10
3
Concorde com @brokenthorn. O ponto mais crucial em seu comentário é "Repositórios são a abstração mais alta", e essa abstração se torna uma necessidade quando você deseja proteger seu código de domínio da tecnologia de banco de dados subjacente. Os conceitos do ORM / Adapter / DB Driver tendem a vazar nos DAOs. Se você possui um aplicativo que oferece suporte a mais de uma tecnologia de banco de dados ou deseja que seu aplicativo não seja bloqueado em um banco de dados, o uso de DAOs diretamente do modelo de domínio não é obrigatório.
Subhash Bhushan
2

Tente descobrir se o DAO ou o padrão de repositório é mais aplicável à seguinte situação: Imagine que você gostaria de fornecer uma API de acesso a dados uniforme para um mecanismo persistente para vários tipos de fontes de dados, como repositórios RDBMS, LDAP, OODB, XML e arquivos simples.

Consulte também os seguintes links, se estiver interessado:

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

em uma frase muito simples: a diferença significativa é que os Repositórios representam coleções, enquanto os DAOs estão mais próximos do banco de dados, geralmente muito mais centrados em tabelas.

Alireza Rahmani Khalili
fonte
O DAO também pode representar coleções / objetos ...
Yousha Aleayoub
0

Na estrutura da primavera, há uma anotação chamada repositório e, na descrição desta anotação, há informações úteis sobre o repositório, que eu acho que são úteis para esta discussão.

Indica que uma classe anotada é um "Repositório", originalmente definido por Domain-Driven Design (Evans, 2003) como "um mecanismo para encapsular o comportamento de armazenamento, recuperação e pesquisa que emula uma coleção de objetos".

As equipes que implementam padrões tradicionais Java EE como "Data Access Object" também podem aplicar esse estereótipo às classes DAO, embora seja necessário ter cuidado para entender a distinção entre o Data Access Object e os repositórios no estilo DDD antes de fazê-lo. Essa anotação é um estereótipo de uso geral e as equipes individuais podem restringir sua semântica e usá-las conforme apropriado.

Uma classe assim anotada é elegível para tradução Spring DataAccessException quando usada em conjunto com um PersistenceExceptionTranslationPostProcessor. A classe anotada também é esclarecida quanto ao seu papel na arquitetura geral do aplicativo para fins de ferramentas, aspectos etc.

Ali Yeganeh
fonte