Padrão DAO vs Repository
Entenda a diferença entre os padrões DAO e Repository: o que cada um encapsula, quando usar cada um e como os dois separam o acesso a dados da regra de negócio.
6 min de leitura atualizado em
Neste artigo
- Entendendo o DAO (Data Access Object)
- E o Repository, então?
- DAO vs Repository: qual a diferença na prática?
- Por que separar o acesso a dados da lógica de negócio?
- Exemplo prático: salvando um aluno
- Exercício guiado: do DAO ao Repository
- Parte 1: um DAO básico
- Parte 2: evoluindo para Repository
- Quando usar cada um?
- Conclusão
Se você já se perguntou qual a diferença entre DAO e Repository, ou se chegou a achar que são a mesma coisa, você está no lugar certo.
Essa dúvida é muito comum entre quem está aprendendo arquitetura de software, e hoje a gente vai resolver ela de vez.
Os dois padrões têm a mesma missão: separar o acesso a dados da lógica de negócio, deixando o código mais organizado, mais limpo e mais fácil de testar.
Mas, apesar de parecerem iguais, eles têm diferenças de intenção e de contexto que fazem toda a diferença na hora de escolher qual usar no seu projeto. Vamos entender isso com calma.
Entendendo o DAO (Data Access Object)
O padrão DAO é, basicamente, uma camada que encapsula o acesso aos dados.
Em vez de sair colocando comandos SQL soltos no meio do código, a gente cria uma classe responsável só por isso, com métodos como:
salvarAluno(Aluno aluno)
buscarPorId(int id)
removerAluno(int id)
Ou seja: operações do tipo CRUD (Create, Read, Update, Delete).
A grande vantagem é que a regra de negócio não precisa saber como os dados estão sendo armazenados. Quem se preocupa com banco de dados, driver JDBC, SQL ou qualquer coisa assim é o DAO.
Em resumo, o DAO:
- trabalha direto com o banco de dados;
- cuida das operações básicas de persistência;
- deixa o restante da aplicação livre dos detalhes de implementação;
- foca mais nos dados em si do que na lógica de negócio.
E o Repository, então?
O padrão Repository vai um passo além.
Ele também isola o acesso a dados, mas com foco no domínio da aplicação, ou seja, nos conceitos e nas regras que fazem sentido no seu sistema.
No Repository, a ideia não é só buscar ou salvar dados. É trabalhar com coleções de objetos do domínio, quase como se fosse uma lista em memória que, por acaso, é guardada num banco.
Por exemplo:
alunoRepository.buscarPorMatricula(String matricula)
alunoRepository.listarAprovados()
Repare que os nomes dos métodos têm mais a ver com o que a aplicação precisa do que com o banco de dados. O Repository já carrega um pouco da inteligência do domínio.
Em resumo, o Repository:
- é comum em projetos que seguem Domain-Driven Design (DDD);
- lida com regras mais próximas da realidade da aplicação;
- trabalha com entidades do domínio, não só com tabelas;
- é mais semântico: reflete o que o sistema faz, não só os dados que ele tem.
DAO vs Repository: qual a diferença na prática?
Muita gente me pergunta:
“Professor, mas no fundo os dois fazem a mesma coisa, né?”
Sim e não. Os dois isolam o acesso aos dados. Mas o DAO olha para o banco. O Repository olha para o domínio.
| DAO | Repository |
|---|---|
| Foco no banco de dados | Foco no domínio da aplicação |
| Métodos CRUD genéricos | Métodos específicos e semânticos |
| Independente do contexto | Inserido no contexto do negócio |
| Mais técnico | Mais conceitual |
Uma forma simples de lembrar:
- DAO: “Preciso salvar este objeto no banco.”
- Repository: “Preciso encontrar os alunos aprovados.”
Os dois vão conversar com o banco, mas o Repository conversa com a lógica da aplicação de forma mais expressiva.
Por que separar o acesso a dados da lógica de negócio?
Essa parte é muito importante. A gente separa porque misturar dá ruim.
Quando você coloca regra de negócio junto com código de banco de dados, vira uma salada difícil de manter, testar e evoluir.
Alguns problemas que essa mistura causa:
- se o banco mudar, você tem que sair caçando SQL pelo código inteiro;
- fica difícil testar, porque qualquer teste depende de um banco de verdade;
- a lógica de negócio fica poluída com comandos que não são dela.
Separando as camadas, cada parte faz o que sabe fazer. A lógica resolve problemas; o DAO ou o Repository cuida do armazenamento.
Exemplo prático: salvando um aluno
Sem separação, a regra e a persistência se misturam:
if (aluno.getNotaFinal() >= 60) {
Connection conn = DriverManager.getConnection(url, usuario, senha);
PreparedStatement ps = conn.prepareStatement("INSERT INTO aluno VALUES (...)");
// ...
}
Com DAO, a regra não sabe mais nada de SQL:
if (aluno.getNotaFinal() >= 60) {
alunoDAO.salvar(aluno);
}
Com Repository, até a regra ganha nome de domínio:
if (aluno.estaAprovado()) {
alunoRepository.adicionar(aluno);
}
Percebe como cada abordagem reflete um nível diferente de abstração?
Exercício guiado: do DAO ao Repository
Este exercício ajuda a enxergar a diferença na prática, começando por um CRUD simples e evoluindo para um contexto orientado ao domínio. Para focar no padrão, o “banco” aqui é uma lista em memória.
Parte 1: um DAO básico
Primeiro, a classe do domínio:
public class Aluno {
private String matricula;
private String nome;
private double notaFinal;
public Aluno(String matricula, String nome, double notaFinal) {
this.matricula = matricula;
this.nome = nome;
this.notaFinal = notaFinal;
}
public boolean estaAprovado() {
return notaFinal >= 60;
}
public String getMatricula() { return matricula; }
public String getNome() { return nome; }
public double getNotaFinal() { return notaFinal; }
}
Agora o DAO, com operações de CRUD:
import java.util.ArrayList;
import java.util.List;
public class AlunoDAO {
private final List<Aluno> bancoFalso = new ArrayList<>();
public void salvar(Aluno aluno) {
bancoFalso.add(aluno);
}
public Aluno buscarPorNome(String nome) {
for (Aluno aluno : bancoFalso) {
if (aluno.getNome().equalsIgnoreCase(nome)) {
return aluno;
}
}
return null;
}
public void remover(Aluno aluno) {
bancoFalso.remove(aluno);
}
public List<Aluno> listarTodos() {
return new ArrayList<>(bancoFalso);
}
}
Aqui o foco está apenas no acesso e na manipulação dos dados. É CRUD puro.
Parte 2: evoluindo para Repository
Agora mudamos a pergunta:
“Queremos um repositório que não apenas guarde alunos, mas que ofereça o que a aplicação precisa.”
import java.util.ArrayList;
import java.util.List;
public class AlunoRepository {
private final List<Aluno> alunos = new ArrayList<>();
public void adicionar(Aluno aluno) {
alunos.add(aluno);
}
public List<Aluno> listarAprovados() {
List<Aluno> aprovados = new ArrayList<>();
for (Aluno aluno : alunos) {
if (aluno.estaAprovado()) {
aprovados.add(aluno);
}
}
return aprovados;
}
public Aluno buscarPorMatricula(String matricula) {
for (Aluno aluno : alunos) {
if (aluno.getMatricula().equals(matricula)) {
return aluno;
}
}
return null;
}
}
Repare em dois detalhes. Primeiro, o Repository fala a língua do domínio: “aprovados”, “matrícula”. Segundo, a regra de aprovação não está no Repository: ele pergunta ao próprio aluno (estaAprovado()). Assim, se a média mudar de 60 para 70, você altera um lugar só.
- DAO foca em salvar e buscar dados.
- Repository foca em comportamentos relevantes para o domínio.
Quando usar cada um?
Use DAO quando:
- o projeto é simples, sem muitas regras de negócio;
- você trabalha com acesso direto ao banco, via JDBC ou SQL escrito à mão;
- a prioridade é velocidade de desenvolvimento.
Use Repository quando:
- o projeto segue DDD;
- as regras de negócio são complexas e precisam ser expressas com clareza;
- você quer um código mais semântico, próximo da linguagem do negócio.
Em projetos pequenos, os dois podem parecer idênticos. A diferença aparece quando o sistema cresce.
Um detalhe que confunde muita gente: no Spring Data JPA, as interfaces se chamam Repository (JpaRepository, CrudRepository), mas, do jeito que costumam ser usadas, com save, findById e delete, elas fazem papel de DAO. O que transforma um repositório em Repository de verdade são os métodos com significado de domínio que você acrescenta.
Conclusão
- DAO e Repository não são rivais. São formas diferentes de resolver o mesmo problema, com focos diferentes.
- O DAO é mais técnico, genérico e voltado para CRUD.
- O Repository é mais semântico, integrado ao domínio da aplicação.
- Em sistemas simples, um DAO pode ser mais que suficiente.
- Em sistemas orientados ao domínio, o Repository brilha.
Como sempre falo nas aulas:
O importante é saber o porquê das coisas. Programar é pensar, e arquitetura boa nasce de decisões conscientes, não de modinha.
Se você entender essa diferença e praticar essa separação desde cedo, seu código vai ser mais limpo, testável, fácil de manter e pronto para crescer.
Bons estudos, e continue explorando com lógica e clareza.