DAO genérica com hibernate

Estou querendo criar uma DAO genérica, para não ter que ficar criando várias DAOs.
Achei um exemplo no site do hibernate, mas com este exemplo tenho que ficar criando várias classes “desnescessáriamente”.
Teria uma maneira de criar uma classe genérica e quando fosse preciso eu criaria uma classe mais espesífica herdando desta classe genérica?

Você pode utilizar generics para criar instancias utilizando a classe desejada.

http://www.guj.com.br/posts/list/58773.java
http://www.urubatan.com.br/dao-generico-um-exemplo-a-pedidos/

Eu já tinha visto estes exemplos.
Em relação ao primeiro eu tinha feito algo parecido, mas quando eu chamava algum método com get a sessão já estava fechada, porque eu fazia que igual ao exemplo dava um commit e fechava a sessão.
O segundo é exemplo é um pouco parecido com o que tem na página do hibernate, é interessante, mas você acaba tendo que criar sempre um DAO para cada classe.
Eu estava querendo algo bem genérico, como por exemplo uma DAO que servisse para todas as DTOs. Claro que quando fosse preciso eu iria especializando, conforme a necessidade.
Vou tentar fazer algo, se conseguiur posto a classe aqui.

Não sei ao certo se é isso que voce quer, mas eu fiz da seguinte maneira:

1. Criei uma interface CustomDao

public interface CustomDao<ENTITY, ID extends Serializable>  {

    public ENTITY recuperarPeloId(ID valorId) throws DaoException;
    public ENTITY salvar(ENTITY entidade) throws DaoException;
    public void excluir(ENTITY entidade) throws DaoException;    
    public void excluirTodos(Collection listaEntidade) throws DaoException;
}

2. Depois criei uma implementaçao CustomDaoImpl para essa interface:

public class CustomDAOImpl <ENTITY extends CustomEntity, ID extends Serializable> extends HibernateDaoSupport implements CustomDao<ENTITY,ID>{

-- código reduzido
    
    public ENTITY recuperarPeloId(ID valorId) throws DaoException{        
        return (ENTITY) getHibernateTemplate().get(getPersistanceClass(), valorId);
    }
    
    public ENTITY salvar(ENTITY entidade) throws DaoException{
        getHibernateTemplate().saveOrUpdate(entidade);
        return entidade;
    }
    
    public void excluir(ENTITY entidade) throws DaoException{
        getHibernateTemplate().delete(entidade);        
    }
    
    public void excluirTodos(Collection listaEntidade) throws DaoException{
        getHibernateTemplate().deleteAll(listaEntidade);
    }

}

3. Quando preciso gravar/recuperar dados de um funcionário, eu crio uma entidade Funcionario.java e um DAO FuncionarioDaoImpl. Repare que na declaraçao da classe FuncionarioDaoImpl, eu passo qual a classe que quero trabalhar e qual o tipo da sua chave primária. Isso é feito usando generics.

@Entity  
@Table(name="FUNCIONARIO", schema = "RH")
public class Funcionario extends CustomEntity <Long> implements java.io.Serializable {

    private Long id;
    private String nome;
    
    
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    @Column(name = "MATRICULA", unique = true, nullable = false, insertable = true, updatable = true, precision = 10, scale = 0)
    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }    
    
    @Column(name = "NOME", unique = false, nullable = false, insertable = true, updatable = true, length = 60)
    public String getNome() {
        return this.nome;
    }

    public void setNome(String nome) {
        this.descricao = descricao;
    }

    @Override
    public String toString() {
        return getDescricao();
    }
}

Classe FuncionarioDAOImpl

public class FormaRecebimentoDAO extends CustomDAOImpl<Funcionario, Long> {
    
}

Para não precisar ficar criando instâncias de FuncionarioDAOImpl nas minhas BackBeans do JSF, eu crio uma propriedade private Dao, um método setDao eu utilizo o Spring para fazer injeção de dependência. Espero ter ajudado.

Entao, eu mudei bastante de conceito no ultimo ano, não concordo mais muito em implementar dao’s genericos e tal, afinal, nem todas suas entidades precisam de save, delete, findAll, ou todos os metodos genericos que o dao generico tem, eu acabo, alem de complicar, dando um monte de possibilidades de ações que nem deveriam ser usadas. Alem do que, quando vc usa JPA/Hibernate, seu dao generico nada mais faz que delegar algo para o Session/EntityManager.
Hoje meu “dao” generico faz apenas a injeção do entityManager (JPA) ou session (hibernate), de resto crio tudo, quando precisar de um save para uma entidade, eu crio, qdo preciso buscar pelo id, eu crio, e assim vai. O sistema fica muito mais “clean”, facil de entender e menos propicio a erros.

Outra dica eh: cuida ao usar DTO, eles tem um proposito especifico e 90% dos casos sao usados de forma errada, fuja do modelo DTO-BO-DAO (o que chamam de modelo anemico), abandonei tambem esse modelo e hj gosto muito mais dos meus sistemas.

Agora vamos ao que te interessa. O dao em si tem uma responsabilidade: acessar dados. A responsabilidade dele não é gerenciar transacoes, ele não inicia nem da commit nelas. Pensa vc realizando uma ação de negócio como por exemplo: criar um pedido.
Ou vc inclui o pedido e todos seus itens ou nao inclui nada, logo vc nao vai iniciar uma transacao para inserir o pedido, dar commit depois iniciar outra transacao para inserir os itens e dar outro commit, todo processo de negocio faz parte da mesma transacao, ou seja, se teus dao’s derem comit sempre, vc tera problemas, entao fica bem claro que a transação é algo que está acima do dao.
O que eu quero dizer com isso é que vc deve programar seus daos esquecendo de transacao. A transacao é algo do sistema como um todo.

Mas beleza, onde fica a transacao? se tiver usando EJB, fica a cargo do servidor de aplicações, senao vc pode usar um framework como o spring, ele possui anotacões para isso e vc configura seu modelo de transacoes nele, com isso basta vc anotar seus objetos (que obviamente devem ser criados pelo spring) como @Transactional que ele gerencia transacoes para vc, essa anotacao segue muito proximo o modelo de EJB. Eu por exemplo marco meus dao’s com Propagation Required, e com isso, caso chegue ao dao sem existir uma transação, uma nova é criada, senão é usada a que já existe. Para entender mais:

http://www.cefetrn.br/~ajdsouza/programacao-III/PDF/Transacoes.pdf
http://static.springframework.org/spring/docs/2.5.x/reference/transaction.html#transaction-declarative

Qualquer tutorial de como configurar hibernate/jpa com spring.