DEV Community

Cover image for Padrões DAO e Repository
Carolina Dias Fonseca
Carolina Dias Fonseca

Posted on

Padrões DAO e Repository

O padrão DAO (Data Access Object ou, em pt-BR, Objeto de Acesso a Dados), é uma abstração de persistência de dados e é considerado próximo da camada de armazenamento de dados que, normalmente, é centrado em tabelas.

Entretanto, em muitos casos, o DAO possui muitas tabelas permitindo, de uma forma mais direta, enviar/receber dados do banco, escondendo as queries mais feias.

Exemplo de implementação:


//Primeiramente, criamos a classe de domínio
public class Usuario{
    private Long id;
    private String nome;
    private String email;

    //getters e setters
}

Enter fullscreen mode Exit fullscreen mode
//Na sequência, criamos uma interface que provê um CRUD simples para a classe de Domínio do Usuário
public interface UsuarioDao{
    void criar(Usuario usuario);
    Usuario buscar(Long id);
    void atualizar(Usuario usuario);
    void deletar(Long id);
}
Enter fullscreen mode Exit fullscreen mode
//Por fim, fazemos a implementação
public class UsuarioDaoImpl implements UsuarioDao{
    private final EntityManager em;

    @Override
    public void criar(Usuario usuario){
        em.persist(usuario);
    }

    @Override
    public Usuario buscar(Long id){
        return em.find(Usuario.class,id);
    }
    //...
}
Enter fullscreen mode Exit fullscreen mode

Padrão Repository

De acordo com Eric Evans em seu livro "Domain-Drive Design", o "repository é um mecanismo para encapsular o banco, recuperar e buscar comportamento que simulam uma coleção de objetos."

Ainda nessa mesma linha, o livro "Padrão de Arquitetura de aplicações Enterprise", do mesmo autor, diz que "entre as camadas de domínio e de mapeamento de dados, utiliza-se uma interface de coleção para acessar os objetos de domínio."

Em outras palavras, o repository também lida com dados e esconde queries de forma semelhante ao padrão DAO. Porém, o repository se trata de uma padrão de alto nível, ou seja, muito mais próximo da lógica de negócio de uma aplicação.

Consequentemente, um repository pode usar um DAO para pegar dados do banco e popular um objeto de domínio, da mesma forma que pode usar um DAO para pegar informações do objeto de domínio e mandar para o armazenamento no banco.

Exemplo de implementação:

public interface UsuarioRepository{
    Usuario get(Long id);
    void adicionar(Usuario usuario);
    void atualizar(Usuario usuario);
    void remover(Usuario usuario);
}
Enter fullscreen mode Exit fullscreen mode
public class UsuarioRepositoryImpl implements UsuarioRepository{

    //Aqui vamos utilizar o DAO
    private UsuarioDaoImpl usuarioDaoImpl;

    @Override
    public Usuario get(Long id){
        return usuarioDaoImpl.buscar(id);
    }

    @Override
    public void adicionar(Usuario usuario){
        usuarioDaoImpl.criar(usuario);
    }

//...
}
Enter fullscreen mode Exit fullscreen mode

Olhando da forma como fizemos até o momento, ambas implementações parecem muito semelhantes, porque a classe Usuario é uma classe de domínio anêmica. E, o repository, é somente outra camada sobre o DAO.

Entretanto, o DAO se torna um candidato perfeito para acesso aos dados enquanto que o Repository é uma forma ideal de se implementar um UseCase.

Um exemplo mais rico sobre o uso do Repository como UseCase:

public class UsuarioRedeSocial extends Usuario{
    private List<Tweet> tweets;
}
Enter fullscreen mode Exit fullscreen mode
public class UsuarioRepositoryImpl implements UsuarioRepository{

    //Aqui vamos utilizar o DAO
    private UsuarioDaoImpl usuarioDaoImpl;
    //Pulamos a etapa de criar o Tweet e TweetDao, mas só para acelerar a compreensão de uma classe de Domínio mais rica
    private TweetDaoImpl

    @Override
    public Usuario get(Long id){
        //não queremos mais apenas salvar o usuário, mas queremos o usuário e seus tweets
        UsuarioRedeSocial usuario = (UsuarioRedeSocial) usuarioDaoImpl.buscar(id);  
        List<Tweet> tweets = tweetDaoImpl.fetchTweets(usuario.getEmail());
        usuario.setTweets(tweets);

        return usuario;
    }

    @Override
    public void adicionar(Usuario usuario){
        usuarioDaoImpl.criar(usuario);
    }

//...
}
Enter fullscreen mode Exit fullscreen mode

Nesse novo exemplo, temos agregação de informação que provê um objeto de domínio que é útil para o nosso UseCase. O poderíamos fazer o mesmo para as demais redes sociais, no mesmo Repository.

Fonte: DAO vs Repository Pattern

Discussion (0)