[Opiniões] Implementação do padrão Repository

E aí, pessoal. Tudo bem?
Bom, estou entendendo como funciona o padrão Repository, e gostaria da opinião de vocês de como estou implementando, para ver se está de acordo!

Bom, primeiramente, eu crio uma classe chamada SessionProvider, que me provê sessões e transações.

public class SessionProvider
{
    private static final SessionFactory sessionFactory = 
        new AnnotationConfiguration().configure().buildSessionFactory();
    private static Session session;
    private static Transaction transaction;
    
    public static Session getSession()
            throws HibernateException
    {
            session = sessionFactory.openSession();
            transaction = session.beginTransaction();
        
            return session;
    }
    
    public static void beginTransaction()
            throws HibernateException
    {
            if ( session != null && session.isOpen() ) {
                
                transaction = session.getTransaction();
                transaction.begin();
            }
    }

    public static void commit()
            throws HibernateException
    {
            if (session.isOpen() && session.isConnected()) {

                transaction.commit();
                session.close();
            }
    }

    public static void rollback()
            throws HibernateException
    {
            if (session.isOpen() && session.isConnected()) {

                transaction.rollback();
                session.close();
            }
    }
}

Bom, eu crio uma Interface para implementá-la com a minha classe Repository:

public interface IRepository<T>
{
    void salvar(T bean) throws HibernateException;
    void deletar(T bean) throws HibernateException;
    T listarPorID(Class clazz, Long handle) throws HibernateException;
}

public class Repository<T> implements IRepository<T>
{
    public void salvar(T bean) 
            throws HibernateException {

        Session session = SessionProvider.getSession();
        session.saveOrUpdate(bean);
    }

    public void deletar(T bean)
            throws HibernateException {

        Session session = SessionProvider.getSession();
        session.delete(bean);
    }

    public T listarPorID( Class clazz, Long handle)
            throws HibernateException {

        Session session = SessionProvider.getSession();

        T bean = (T) session.load( clazz, handle );
        return bean;
    }
}

Aqui, eu tenho uma dúvida: vejam o método ListarporID. Bom, é necessário que eu passe a classe por parâmetro para procurar o objeto no banco de dados. Usando .NET, eu poderia fazer T bean = session.Load( typeof(T), handle ); que eu não precisaria do parâmetro clazz. Há algum meio de fazer isso no JAVA?

Bom, continuando…
A partir daí, eu crio uma Interface para as classes repositório que eu possuo. Aqui vai um exemplo com uma classe Usuário:

public interface IUsuarioRepository
{
    List<Usuario> listarTodosUsuarios();
    List<Usuario> listarUsuariosAtivos();
    List<Usuario> listarUsuariosInativos();
    //...
}

public class UsuarioRepository 
        extends Repository<Usuario> implements IUsuarioRepository
{
    public List<Usuario> listarTodosUsuarios() {

        Criteria criteria;
        Session session;
        
        session = SessionProvider.getSession();

        criteria = session.createCriteria( Usuario.class );
        List<Usuario> usuarios = criteria.list();

        return usuarios;
    }
    // e por aí vai...
}

Também tenho minhas classes Controllers, que fazem uso dos repositórios.

public class UsuarioController
        implements IUsuarioController
{
    private UsuarioRepository repository = new UsuarioRepository();

    public void salvarUsuario( Usuario usuarion ) {

        SessionProvider.beginTransaction();
        repository.salvar( usuario );
        SessionProvider.commit();
    }
}

E minhas classes View fazem chamadas às classes Controllers, requisitando as operações.
E aí, você acham que a arquitetura tá condizente?
Vejam que não fiz uso de classes DAO. O que vocês acham disso?

Agradeço qualquer opinião!
Valeu galera! :smiley:

Eu não sei se está certo a sua implementação, mas não gosto dessa abordagem. Vamos aos pontos:

  1. NUNCA faça uso de exceções da sua infra no seu domínio (repository)
  2. Repositório, ao meu ver, não pode conhecer como os dados serão armazenados.
    Então eu faria da seguinte maneira:

Uma interface UsuarioRepository, com os métodos relacionados a ele;
Uma classe UsuarioDao que implementaria esse repository;
Suas entidades e controller apenas conheceriam UsuarioRepository, e fariam chamadas aos seus métodos.

Bom, acho que é isso.

[]'s

Nicolas, veja se serve.

public class Repository&lt;T&gt; implements IRepository&lt;T&gt;  
{  
     public T listarPorID(Long handle)  
             throws HibernateException {  
   
         Session session = SessionProvider.getSession();  
   
         T bean = (T) session.load((Class&lt;T&gt;) getParamType(), handle );  
         return bean;  
     }  

     protected Type getParamType() {
        Type argType = null;

        Class&lt;?&gt; thisType = this.getClass();
        while (thisType != null && argType == null) {

            final Type genericType = thisType.getGenericSuperclass();

            if (genericType != null && genericType instanceof ParameterizedType) {
                argType = ((ParameterizedType) genericType).getActualTypeArguments()[0];
            }

            thisType = thisType.getSuperclass();
        }

        return argType;
    }

  ...

}