Pular para o conteúdo
blog

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.

Prof. José Rui

6 min de leitura atualizado em

Neste artigo
  1. Entendendo o DAO (Data Access Object)
  2. E o Repository, então?
  3. DAO vs Repository: qual a diferença na prática?
  4. Por que separar o acesso a dados da lógica de negócio?
  5. Exemplo prático: salvando um aluno
  6. Exercício guiado: do DAO ao Repository
  7. Parte 1: um DAO básico
  8. Parte 2: evoluindo para Repository
  9. Quando usar cada um?
  10. 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.

DAORepository
Foco no banco de dadosFoco no domínio da aplicação
Métodos CRUD genéricosMétodos específicos e semânticos
Independente do contextoInserido no contexto do negócio
Mais técnicoMais 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.

# continue lendo

Mais artigos para você