Repository Exemplo pratico

Ola Pessoal!

Desde já adianto-lhes que ja pesquisei bastante incluive aqui no Forum, mas nao encotrei algum exemplo de implementação pratica do pattern Repository.
Tudo que encontro é teoria, descrição e coisas a mais.

Gostaria de saber se alguem tem algo simples, so pra ver o funcionamento pois ainda não consegui assimilar a exencia deste padrão.

Obrigado desde já!

Um Repository pode ser uma camada de abstração acima da sua persistência.
Por exemplo, se vc quer persistir os dados de um usuário no banco, sua logica ou oq quer que seja vai trabaçhar com o repositorio:

interface RepositorioInterface {
   public void adiciona (Object o);
   public List<Object> listaTudo ();
}
class UsuarioRepositorio extends Dao<Usuario> implements RepositorioInterface {

   public void adiciona (Usuario u) {
     this.manager.persist(u);
   }
}

Não sei se fui claro o bastante, mas a idéia principal creio que seja essa: vc não tem que encostar no seu Dao, e qdo vc quiser persistir em qq outra coisa (em outro BD, na RAM, num “kfdba”, etc…), vc não precisa mexer no seu repositorio. Encaro o repository como uma caixa-preta onde vc trabalha com objetos que serão persistidos em algum lugar, de alguma forma que o repository não sabe como. Eu encaro isso como uma ótima divisão de responsabilidades.

Espero ter ajudado. Abraço.

Ah, faltou uma coisa, o “this.manager” é um EntityManager que é herdado pela classe Dao ok?

leandronsp , Obrigado pelo exemplo.

Mas como tinha falado, entendi o que o padrão trata,nao entendi como implementa-lo…

E tambem nao encontrei nenhum exemplo na net…

Obg…!

MAs é assim que vc implementa.
Vamos lá, vc pode criar uma Interface RespositorioInterface <G> generica, que contem os metodos (adicionar, remover, listar) qualquer objeto <G> certo?
Crie também uma interface RepositorioFactoryInterface, que contem os metodos (beignTransaction, commit, rollback,…).

A partir daí, sua estrutura de Repositorio já está criada! Qualquer persistencia pode implementa-la.

Para implementá-la, vc cria seu Dao <Generico>, que implementa o RepositorioInterface generico (adicionar, remover, dasfadsfdfa, etc…).
Depois o DaoFactory, que implementa o RepositorioFactoryInterface. (getTransaciton, commit, close, etc)

Pronto, sua estrutura generica de repositorio e Daos já está montada.
No caso de persistencia mais especifica, podemos criar uma interface UsuarioRepositorioInterface, que extende a interface RepositorioInterface<Usuario>. É uma interface herdando a outra.
Essa interface UsuarioRepositorioInterface assina metodos especificos para Usuario. (getUsuarioPorIdade, listaUsuariosInadimplentes, etc…)

Por ultimo, o UsuarioDao que extende (herda) Dao<Usuario> (com seu manager, transaction) e implementa UsuarioRepositorioInterface. (os metodos especificos).

Se vc montar toda essa estrutura vai perceber que parece um ‘Dao dentro de outro Dao’. Mas vc já sabe a vantagem disso.
Fui claro agora? Qq duvida posta de novo. E se por acaso errei algo pessoal, favor corrigir.

[]´s

Vamos implementar a persistência de um usuário no BD, utilizando uma camada a mais de abstração, a REPOSITORY.

Precisamos de uma interface que forneça assinatura de métodos para persistência:

public interface RepositorioInterface&lt;T&gt; {

    public void adicionar(T objeto);
    
    public void remover(T objeto);
}

Precisamos também de outra interface que forneça assinatura de métodos para a “fábrica” de RepositorioInterface:

public interface RepositorioFactoryInterface {

    public void beginTransaction();

    public void commit();

    public UsuarioRepositorioInterface getUsuarioRepositorio();
 
    public QualquerCoisaRepositorioInterface getQualquerCoisaRepositorio();
}

Até agora, o que temos são métodos genéricos para implementação (métodos comuns a qualquer entidade e DaoFactory).
Mas como queremos persistir um usuário, é interessante criar uma interface de repositorio comum para usuario, que contém assinatura de métodos para persistência “típica” de usuarios no sistema:

public interface UsuarioRepositorioInterface extends RepositorioInterface&lt;Usuario&gt; {

    public List&lt;Usuario&gt; getUsuariosDaFaculdade(Faculdade faculdade);
}

Agora, para realmente persistir, no caso com JPA e Hibernate, criamos um Dao<T> genérico que implementa os métodos da interface RepositorioInterface<T>, que recebe no construtor um EntityManager:

public class Dao&lt;T&gt; implements RepositorioInterface&lt;T&gt; {

    protected final EntityManager em;
    private Classe classe;

    public Dao(EntityManager em, Class classe) {
        this.em = em;
        this.classe = classe;
    }

    public T atualizar(T t) {
        return this.em.merge(t);
    }

    public void remover(T t) {
        this.em.remove(t);
    }

   //get, set
}

O DaoFactory, que implementa os métodos da interface RepositorioFactoryInterface:

public class DaoFactory implements RepositorioFactoryInterface {

    protected final EntityManager em;
    private EntityTransaction transaction;

    public DaoFactory() {
        em = JPAUtil.getEntityManager();
    }

    public void beginTransaction() {
        this.transaction = em.getTransaction();
        this.transaction.begin();
    }

    public void commit() {
        this.transaction.commit();
        this.transaction = null;
    }

    public UsuarioRepositorioInterface getUsuarioRepositorio() {
        return new UsuarioRepositorioDao(em, classe);
    }
}

E por fim, o UsuarioRepositorioDao, que herda Dao<Usuario> e implementa os métodos da interface UsuarioRepositorioInterface:

public class UsuarioRepositorioDao extends Dao&lt;Usuario&gt; implements UsuarioRepositorioInterface {

    public UsuarioRepositorioDao(EntityManager em, Class classe) {
        super(em, classe);
    }

    public List&lt;Usuario&gt; getUsuariosDaFaculdade(Faculdade faculdade, int inicio, int quantidade) {
        Query q = getQuery("SELECT u FROM Usuario u WHERE u.faculdade = :faculdade order by u.avatar desc, u.ultimoLogin desc");
        q.setHint("org.hibernate.cacheable", true);
        q.setParameter("faculdade", faculdade);
        q.setFirstResult(inicio);
        q.setMaxResults(quantidade);
        return getQueryResultList(q);
    }

    public List&lt;Usuario&gt; getUsuariosDaFaculdade(Faculdade faculdade) {
        return getUsuariosDaFaculdade(faculdade, 0, 6);
    }
}

Esta foi uma forma simples de implementar o REPOSITORY. A vantagem aí está que se eu tiver que alterar minha forma de persistência, altero apenas os Dao´s, tendo que apenas implementar os métodos impostos pelas interfaces REPOSITORY.
Espero ter ajudado.
[]´s