Meu Generic DAO - Opinião e Crítica

[quote=AdemirPinto]

Então maior_abandonado, com relação à session eu vou usar algum start msm, eu uso o PhaseListeners para segurança, poderia usar ele pra iniciar e fechar a sessão? Agora e a transação como eu poderia fazer? Neste meu projeto eu estou usando JSF 2, JPA 2 e Hibernate 3. Não estou querendo pindurar muitos frameworks para nao ficar confuso. Mas qualquer sugestão é bem vinda.

Abraços e mais uma vez muito obrigado.
Ademir[/quote]

você pode usar mais de um PhaseListener, um para gerenciar a sessão do hibernate e outro para segurança, para ver se o usuário está logado por exemplo… nada impede… você pode também continuar gerenciando a sessão do hibernate em um Filter (nada impede).

quanto a abrir a transação, commitar ou dar rollback, eu indico você a chamar isso na sua classe de negócio la no modelo mesmo, na sua classe de negócio você pega a sessão ativa, faz tudo o que tem que fazer, se der alguma exceção (seja de negócio, de banco de dados), você pode dar algum rollback no catch dali, lançando ainda a exceção para o controller para ele saber disso e informar o usuário.

[quote=maior_abandonado]eu achei legal por que deu para ver que você caprichou… pensou em fazer tomando cuidado com os detalhes…até por quÊ ficou grande… confesso que também não li tudo com calma, só dei uma olhadinha.

Algumas dicas que a experiência e alguns estudos demonstram para agente:

Evite deixar o dao gerenciar sua session do hibernate… assim fica mais dificil de você sempre fecha-la da forma correta… sempre passe a sessão para o seu Dao e caso ela esteja fechada lance uma exceção por exemplo… dao não deveria abrir sessão, o seu modelo, seila, seu BO deve abrir a sessão, passar uma sessão válida para os daos fazerem o que tiverem que fazer e ai no BO você comita ou da rollback caso tenha dado erro, assim vai comitar ou rollbackear tudo o que foi feito (a menos que a regra de negócio seja comitar só uma metade caso só ela tenha dado certo e dar rollback no que não deu, o que eu nunca vi, e mesmo que seja essa a ideia, dao não é lugar de regra de negócio, é lugar de operação com o banco pura e simples). Não se esqueça de ter um try catch no seu BO dando commit no final do try, rollback no catch.

quanto aos try catchs do dao, eles serão necessários caso você queira fazer alguma coisa em caso de erro (obvio, é a utilidade mais básica do try catch…). Como acabei de indicar você a deixar o rollback em outro lugar ele a principio não teria mais utilidade, mas eu te indico que em caso de erro você gere um log no dao dizendo o que vocÊ estava tentando inserir/atualizar/busca/deletar… logando por exemplo a classe e método do seu dao e o toString do pojo que você estava tentando… fazer o que estava fazendo, assim é facil detectar o que aconteceu no futuro em caso de algum erro. Ja que seria esse log só no caso de erro, ele deve ficar no catch, tornando-o necessário, não se esqueça de dar o throw depois disso para avisar a camada de cima (um BO por exemplo) que o erro aconteceu, assim ela pode tomar a decisão que precisar, dar o rollback na sessão do hibernate, avisar o controller para que este então redirecione para uma tela de erro por exemplo. Eu gosto de além de logar no dao quais eram as informações que deu erro ao inserir por exemplo, logar no modelo alguma coisa do tipo “erro ao …”.

Procure deixar seus pojos sempre com o fech Lazy, para ficar mais leve ao obter suas entidades no banco. é possivel que vocÊ tenha problemas de Lazy Innicialization, a dica abaixo resolve.

Para gerenciar como você abre sua sessão do hibernate (e como fecha), eu te aconselharia ver o padrão Open Session In View…

essa é uma leitura muito boa, mas isso é só mais para frente…

bom… no demais parabéns… gostei muito do seu dao e se me permite peço para pegar ele e adapta-lo…[/quote]

referente a como abrir oou fechar o hibernate não seria legal deixar com o HibernateTemplate do Spring?

Abraços!

honestamente não conheço spring…

conheço injeção de dependencia, sei que da para injetarmos a sessão mas ai nem entrei no que ele poderia fazer com o spring por quê não conheço o framework… estava me referindo ao padrão mesmo.

mas então… o que o HibernateTemplate faz?

Pessoal,

segui alguns conselhos do pessoal e melhorei bem meu Generic DAO(parte do código abaixo)…muito obrigado a todos.

Só que ainda falta alguns detalhes e dentre eles a questão da Sessão e Transação. Com relação à sessão eu fiz um filter para criar ele e depois em cada requisição eu a recupero, conforme o código abaixo. As dúvidas ainda são:

1)Vocês acham que ficou bom meu HibernateSessionRequestFilter?

2)Estava pensando em fazer o controle de transação nos meus Managed Bean, o que voces acham?

3)No site http://community.jboss.org/wiki/OpenSessioninView tem uma implementação com o controle de transação no filter, isso não é complicado? Tipo eu quero fazer um controle melhorar das minhas exceções para tratar a saida para o usuario. Outra coisa é que ele fica dando beginTransaction e depois commit, mas pode acontecer que a requisição não alterou o banco de dados. O que vocês acham dessa implementação? Vale a pena fazer o controle de transação assim?

HibernateSessionRequestFilter:[code]
public class HibernateSessionRequestFilter implements Filter {

private SessionFactory sf;

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    try {
        chain.doFilter(request, response);
    } catch (Throwable ex) {
        ex.printStackTrace();
        throw new ServletException(ex);
    }
}

public void init(FilterConfig filterConfig) throws ServletException {
	System.out.println("Initializing filter...");
	System.out.println("Obtaining SessionFactory from static HibernateUtil singleton");
	sf =  HibernateUtil.getInstace().getSessionFactory();     
	sf.openSession(); 
}

public void destroy() {
	
}

}
[/code]
HibernateUtil:[code]
public class HibernateUtil {

private static HibernateUtil me;
private SessionFactory sessionFactory;

public HibernateUtil() {
	sessionFactory = new Configuration().configure().buildSessionFactory();
}

public Session getSession() {
	Session toReturn = sessionFactory.openSession();
	return toReturn;
}

public static HibernateUtil getInstace() {
	if (me == null) {
		me = new HibernateUtil();
	}
	return me;
}

public SessionFactory getSessionFactory() {
	return sessionFactory;
}

public void setSessionFactory(SessionFactory sessionFactory) {
	this.sessionFactory = sessionFactory;
}

}
[/code]
GenericDAO:[code]
@SuppressWarnings(“unchecked”)
public class GenericDAO {

@SuppressWarnings("rawtypes")
private Class persistentClass;
private Session session;

//Construtor - ##########################################
@SuppressWarnings("rawtypes")
protected GenericDAO(Class p_persistentClass) {
	session = HibernateUtil.getInstace().getSession();		
	persistentClass = p_persistentClass;
}

public Session getSession() {
	return session;
}

@SuppressWarnings("rawtypes")
public Class getPersistentClassLocal(){
	return persistentClass;
}

public void insert(T obj) throws Exception {		
	session.save(obj);
	session.flush();
}

public void update(T obj) throws Exception {
	session.update(obj);
	session.flush();
}

public void delete(T obj) throws Exception {
	session.delete(obj);
	session.flush();
}

public Integer count(List<Criterion> criterion) throws Exception {
	Criteria criteria = session.createCriteria(persistentClass);
		
	for (Criterion c: criterion)
		criteria.add(c);
		
	criteria.setProjection(Projections.rowCount());
	return ((Integer) criteria.uniqueResult()).intValue();
}

//Lista todos os registros com ordem e sem limite
public List<T> listAll(String fieldOrder, SortOrder sortOrder) throws Exception {
	String ord = ConstantesGerais.TIPOORDEMASC; 
	if (sortOrder == SortOrder.DESCENDING)  
		ord = ConstantesGerais.TIPOORDEMDESC;  
		
	Criteria criteria = session.createCriteria(persistentClass);
	addOrder(criteria, fieldOrder, ord);
	return criteria.list();
}

[/code]

Abraços a todos e um bom FDS.
Ademir

[quote=maior_abandonado]honestamente não conheço spring…

conheço injeção de dependencia, sei que da para injetarmos a sessão mas ai nem entrei no que ele poderia fazer com o spring por quê não conheço o framework… estava me referindo ao padrão mesmo.

mas então… o que o HibernateTemplate faz?[/quote]

Ele encapsula o código do Hibernate deixando um template para uso… gosto muito pelo fato que não fica aquelas classes como o HibernateUtil…

[quote=AdemirPinto]Pessoal,

segui alguns conselhos do pessoal e melhorei bem meu Generic DAO(parte do código abaixo)…muito obrigado a todos.

Só que ainda falta alguns detalhes e dentre eles a questão da Sessão e Transação. Com relação à sessão eu fiz um filter para criar ele e depois em cada requisição eu a recupero, conforme o código abaixo. As dúvidas ainda são:

1)Vocês acham que ficou bom meu HibernateSessionRequestFilter?

2)Estava pensando em fazer o controle de transação nos meus Managed Bean, o que voces acham?

3)No site http://community.jboss.org/wiki/OpenSessioninView tem uma implementação com o controle de transação no filter, isso não é complicado? Tipo eu quero fazer um controle melhorar das minhas exceções para tratar a saida para o usuario. Outra coisa é que ele fica dando beginTransaction e depois commit, mas pode acontecer que a requisição não alterou o banco de dados. O que vocês acham dessa implementação? Vale a pena fazer o controle de transação assim?

HibernateSessionRequestFilter:[code]
public class HibernateSessionRequestFilter implements Filter {

private SessionFactory sf;

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    try {
        chain.doFilter(request, response);
    } catch (Throwable ex) {
        ex.printStackTrace();
        throw new ServletException(ex);
    }
}

public void init(FilterConfig filterConfig) throws ServletException {
	System.out.println("Initializing filter...");
	System.out.println("Obtaining SessionFactory from static HibernateUtil singleton");
	sf =  HibernateUtil.getInstace().getSessionFactory();     
	sf.openSession(); 
}

public void destroy() {
	
}

}
[/code]
HibernateUtil:[code]
public class HibernateUtil {

private static HibernateUtil me;
private SessionFactory sessionFactory;

public HibernateUtil() {
	sessionFactory = new Configuration().configure().buildSessionFactory();
}

public Session getSession() {
	Session toReturn = sessionFactory.openSession();
	return toReturn;
}

public static HibernateUtil getInstace() {
	if (me == null) {
		me = new HibernateUtil();
	}
	return me;
}

public SessionFactory getSessionFactory() {
	return sessionFactory;
}

public void setSessionFactory(SessionFactory sessionFactory) {
	this.sessionFactory = sessionFactory;
}

}
[/code]
GenericDAO:[code]
@SuppressWarnings(“unchecked”)
public class GenericDAO {

@SuppressWarnings("rawtypes")
private Class persistentClass;
private Session session;

//Construtor - ##########################################
@SuppressWarnings("rawtypes")
protected GenericDAO(Class p_persistentClass) {
	session = HibernateUtil.getInstace().getSession();		
	persistentClass = p_persistentClass;
}

public Session getSession() {
	return session;
}

@SuppressWarnings("rawtypes")
public Class getPersistentClassLocal(){
	return persistentClass;
}

public void insert(T obj) throws Exception {		
	session.save(obj);
	session.flush();
}

public void update(T obj) throws Exception {
	session.update(obj);
	session.flush();
}

public void delete(T obj) throws Exception {
	session.delete(obj);
	session.flush();
}

public Integer count(List<Criterion> criterion) throws Exception {
	Criteria criteria = session.createCriteria(persistentClass);
		
	for (Criterion c: criterion)
		criteria.add(c);
		
	criteria.setProjection(Projections.rowCount());
	return ((Integer) criteria.uniqueResult()).intValue();
}

//Lista todos os registros com ordem e sem limite
public List<T> listAll(String fieldOrder, SortOrder sortOrder) throws Exception {
	String ord = ConstantesGerais.TIPOORDEMASC; 
	if (sortOrder == SortOrder.DESCENDING)  
		ord = ConstantesGerais.TIPOORDEMDESC;  
		
	Criteria criteria = session.createCriteria(persistentClass);
	addOrder(criteria, fieldOrder, ord);
	return criteria.list();
}

[/code]

Abraços a todos e um bom FDS.
Ademir[/quote]

Referente a Sessão e Transação estude Spring:

Transaction Management
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/transaction.html

Outra coisa, use o Spring tambem para evitar o HibernateUtil…

Abraços!

[quote=AdemirPinto]Pessoal,

segui alguns conselhos do pessoal e melhorei bem meu Generic DAO(parte do código abaixo)…muito obrigado a todos.

Só que ainda falta alguns detalhes e dentre eles a questão da Sessão e Transação. Com relação à sessão eu fiz um filter para criar ele e depois em cada requisição eu a recupero, conforme o código abaixo. As dúvidas ainda são:

1)Vocês acham que ficou bom meu HibernateSessionRequestFilter?

2)Estava pensando em fazer o controle de transação nos meus Managed Bean, o que voces acham?

3)No site http://community.jboss.org/wiki/OpenSessioninView tem uma implementação com o controle de transação no filter, isso não é complicado? Tipo eu quero fazer um controle melhorar das minhas exceções para tratar a saida para o usuario. Outra coisa é que ele fica dando beginTransaction e depois commit, mas pode acontecer que a requisição não alterou o banco de dados. O que vocês acham dessa implementação? Vale a pena fazer o controle de transação assim?

HibernateSessionRequestFilter:[code]
public class HibernateSessionRequestFilter implements Filter {

private SessionFactory sf;

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    try {
        chain.doFilter(request, response);
    } catch (Throwable ex) {
        ex.printStackTrace();
        throw new ServletException(ex);
    }
}

public void init(FilterConfig filterConfig) throws ServletException {
	System.out.println("Initializing filter...");
	System.out.println("Obtaining SessionFactory from static HibernateUtil singleton");
	sf =  HibernateUtil.getInstace().getSessionFactory();     
	sf.openSession(); 
}

public void destroy() {
	
}

}
[/code]
HibernateUtil:[code]
public class HibernateUtil {

private static HibernateUtil me;
private SessionFactory sessionFactory;

public HibernateUtil() {
	sessionFactory = new Configuration().configure().buildSessionFactory();
}

public Session getSession() {
	Session toReturn = sessionFactory.openSession();
	return toReturn;
}

public static HibernateUtil getInstace() {
	if (me == null) {
		me = new HibernateUtil();
	}
	return me;
}

public SessionFactory getSessionFactory() {
	return sessionFactory;
}

public void setSessionFactory(SessionFactory sessionFactory) {
	this.sessionFactory = sessionFactory;
}

}
[/code]
GenericDAO:[code]
@SuppressWarnings(“unchecked”)
public class GenericDAO {

@SuppressWarnings("rawtypes")
private Class persistentClass;
private Session session;

//Construtor - ##########################################
@SuppressWarnings("rawtypes")
protected GenericDAO(Class p_persistentClass) {
	session = HibernateUtil.getInstace().getSession();		
	persistentClass = p_persistentClass;
}

public Session getSession() {
	return session;
}

@SuppressWarnings("rawtypes")
public Class getPersistentClassLocal(){
	return persistentClass;
}

public void insert(T obj) throws Exception {		
	session.save(obj);
	session.flush();
}

public void update(T obj) throws Exception {
	session.update(obj);
	session.flush();
}

public void delete(T obj) throws Exception {
	session.delete(obj);
	session.flush();
}

public Integer count(List<Criterion> criterion) throws Exception {
	Criteria criteria = session.createCriteria(persistentClass);
		
	for (Criterion c: criterion)
		criteria.add(c);
		
	criteria.setProjection(Projections.rowCount());
	return ((Integer) criteria.uniqueResult()).intValue();
}

//Lista todos os registros com ordem e sem limite
public List<T> listAll(String fieldOrder, SortOrder sortOrder) throws Exception {
	String ord = ConstantesGerais.TIPOORDEMASC; 
	if (sortOrder == SortOrder.DESCENDING)  
		ord = ConstantesGerais.TIPOORDEMDESC;  
		
	Criteria criteria = session.createCriteria(persistentClass);
	addOrder(criteria, fieldOrder, ord);
	return criteria.list();
}

[/code]

Abraços a todos e um bom FDS.
Ademir[/quote]

o melhor mesmo é você usar algum framework para gerenciar isso, como o spring que nosso amigo citou… eu ja testei uns negocios legais semelhantes a isso com EJB também, o “HibernateUtils” passa a ser desnecessário (ele injeta o seu “gerenciador de conexões” que é semelhante a session do hibernate, da o commit ou rollback automatico… enfim), mas supondo que você não vá usar isso, algumas dicas:

No hibernateUtils, normalmente se diexa o construtor dele privado, para que ninguém consiga instanciar essa classe, para se obter instancias dele deve-se usar um método public static getInstance, para então a partir deste se obter a sessão pelo getSession, ou então nem criar o getInstance, deixando o getSession estatico também para ser acessivel de fora do objeto (eu gosto de fazer dessa forma ja que este é o unico método que deixo acessivel nessa classe). Não deixo getters e setters do seu SessionFactory, classes de fora não deveriam acessa-lo, apenas a própria classe de dentro para criar sessões, se você tiver deixado o getSession estático, você deixaria também o sessionFactory estático inicializaria ele em um bloco também estatico.

Veja esse exemplo, estou sem ide, podem ter erros de digitação e por isso não compilar:

[code]public class HibernateUtil {

private static HibernateUtil me;  
private static SessionFactory sessionFactory;  

static {  
    sessionFactory = new Configuration().configure().buildSessionFactory();  
}  

public static Session getSession() {  
    Session toReturn = sessionFactory.openSession();  
    return toReturn;  
}  

}[/code]

o formato do padrão singleton normalmente é aquele que expliquei, construtor privado, uma instancia de si própria usado no getInstance (do jeito que você estava usando), e ai o getSession, seria o mesmo que você estava fazendo sem permitir acesso ao sessionFactory e com o construtor privado, mas acho que desse jeito é melhor, não precisa ficar chamando getInstance e não tem por que trabalhar com objetos neste caso.

O seu filter também não está 100 %, repare que sua sessão nunca é fechada, nem disponibilizada de alguma forma para o modelo, desse jeito não sei como você obteria ela no seu modelo, vocÊ ainda precisaria chamar o hibernateUtils la, sendo que esse filtro é justamente para vocÊ não fazer isso, veja o exemplo abaixo:

ps. editei por que vi que do jeito que estava a sessão ficaria fora de escopo na hora de fechar…

[code]public class HibernateSessionRequestFilter implements Filter {

public static String HIBERNATE_SESSION_NAME = "sessao_hibernate";

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {  
    Session s = null;
    try {
		//prefira usar algum log de verdade para isso	
		System.out.println("Obtaining SessionFactory from static HibernateUtil singleton");  
		s = HibernateUtil.getSession();
		HttpSession httpSession = ((HttpServletRequest) request).getSession(true);
		httpSession.setAttribute(HIBERNATE_SESSION_NAME, s);
		
        chain.doFilter(request, response);  
    } catch (Throwable ex) {  
        ex.printStackTrace();  
        throw new ServletException(ex);  
    }

	try {
		if (s != null) s.close();
    } catch (Throwable ex) {  
		//logar aqui
        ex.printStackTrace();  
    }
}  

public void init(FilterConfig filterConfig) throws ServletException {  
      
}  

public void destroy() {  
      
}  

} [/code]

assim no seu modelo você pegaria sua sessão e obteria a sessão do hibenrate na sessão pelo nome chapado na constante existente no filtro.

a, mesmo que vocÊ use algum framework, é interessante você entender este conceito…

editando denovo… agora que eu vi seu item 2… se você colocar o gerenciamento das transações no controller, ai o seu modelo fica ± dependente dele. O ideal é você desacoplar ao máximo as camadas… vamos a um exemplo: se o seu cliente quiser portar a aplicação que está sendo feita de web para destop por exemplo, como você está desenvolvendo em camadas e tem uma camada de modelo na aplicação web, pode pode colocar essa camada interinha na aplicação desktop certo? ai no controller da sua aplicação desktop você só chama o modelo e ele ja faz tudo o que tem que fazer… estranhamente o modelo para inserir clientes (exemplo) não loga nenhum erro, a aplicação fala que cadastrou com sucesso mas o dado não ta la na base… depois de muito analisar o código você vê que não commitou, isso por que o commit ou rollback ficaria no controller, você não copiou o controller e esqueceu de re-escrever isso na app desktop. Ja descobrimos ai dois problemas, o primeiro é que uma camada tem certa dependencia da camada acima, o que não é o ideal, o segundo problema é que você está re-escrevendo código. Se você tivesse colocado isso no modelo la certiho, não teria nenhum destes problemas. Sim dessa forma leva um pouco mais de tempo e da um pouco mais de trabalho… no desenvolvimento do software, mas com certeza você terá menos trabalho e gastará menos tempo na manutenção (seja por correções, seja por alterações), e acredite, o normal é gastar mais tempo na manutenção de um software do que na construção…

a se la para frente alguém decidir alterar o framework mvc você terá os mesmos problemas que no exemplo que eu citei.

nessa thread, que é de outro assunto mais ai o assunto mudou para “colocar o modelo no managed bean do jsf”, eu tentei explicar resumidamente o por que de isso ser uma ideia ruim…

Fala maior_abandonado, como te falei to quase chegando lá.

Me fala uma coisa na linha 10 da classe HibernateSessionRequestFilter vc tem “s = HibernateUtil.getSession();”, pq vc nao usa isso na init do HibernateSessionRequestFilter?
Pq no http://community.jboss.org/wiki/OpenSessioninView o getSessionFactory() fica na init?

Abraços
Ademir

bom… vamos primeiro ao conceito de quando estes métodos são chamados:

O init é chamado quando a filter é iniciada, colocada em funcionamento.

o destroy é chamado quando a filter é retirada do funcionamento.

o doFilter é chamado sempre que ocorre uma requisição. Quando você chama o filter.chain é passada para frente a requisição, de forma que o código que você deixar antes disso executa antes da requisição prosseguir para o que quer que ela tenha interceptado, o que você codificar depois disso vai acontecer depois da requisição terminar.

eu nem tenho certeza se eu tinha te explicado a ideia do open session in view, a ideia é a seguinte, quando o usuário vai requisitar uma página, você abre a sessão, usa ela para tudo o que tiver que fazer ali para aquela requisição do usuário e depois de ter feito isso fecha essa sessão. Por isso estou abrindo a sessão no doFilter antes de chamar o chain e fechando depois de chama-lo, para fazer oq ue descrevi acima. Supomos que nós abrissemos a sessão no init e os managed beans usassem ela (supondo que você tivesse disponibilizado ela para seus managed beans ali por exemplo. Todas as requisições de todos os usuários usariam essa mesma sessão, inclusive requisições concorrentes estariam usando a mesma sessão (isso não é bom). De qualquer forma feito isso, se vocÊ abrir sua sessão no innit vocÊ deverá fecha-la no destroy (você sempre deve fechar sua sessão/conexão com o banco/devolver recursos que estiver usando).

Fala maior_abandonado,

saquei o que vc disse. Achava que o init era por sessão(http) de usuário e nao para todas as sessões. Uma outra dúvida, fiz a minha segurança no PhaseListener, mas será que não seria melhor no Filter? Pesquisei na net e aqui no forum, mas as opiniões são divergentes. Não existe um evento que é disparado por nova sessão http?
A propriedade do Hibernate “hibernate.current_session_context_class” deve ser managed ou thread para open session in view?

Qnd tiver redondinho aqui vou compartilhar os fontes pro pessoal ter acesso.

Grande abraços e mais uma vez muito obrigado.
Ademir

quanto a usar o PhaseListener ou a Servlet Filter, eu acredito no seguinte: se você conhecer bem como funcionam as fases do jsf e souber assim usar bem o PhaseListener, tanto faz… simples assim, então se é uma coisa que vai ser verificada em qualquer requisição por exemplo e apenas uma vez a cada requisição, eu prefiro filter unicamente por que é masi facil… isso é um gosto pessoal, cada um pode preferir de uma forma, porém se você quer alguma outra coisa especifica para o jsf, especialmente se for em uma das fases da requisição do jsf, ai phaseListener é mais indicado. Use aquele que vocÊ se sentir mais seguro.

quanto ao “hibernate.current_session_context_class”, não costumo configurar isso, fiquei sabendo o que é agora :roll:. Dei uma pesquisada e aqui estão indicando usar managed.

Na verdade, pode-se até desconsiderar o uso do Filter do Servelet usando o PhaseListener do JSF, uma coisa pode substituir a outra. Apesar que até hoje, só encontrei aplicações feitas usando o Filter mesmo.

Pessoal,

depois de pesquisar muito e principamente da ajuda deste forum estou liberando minhas classes: SessionFactoryUtil, HibernateSessionUtil, HibernateSessionFilter e GenericDAO.
O projeto é web e usando Open Session View. Por enquanto não estou usando IoC e nem Spring já que estou iniciando no mundo java.
Gostaria da avaliação e críticas de vcs não usando IoC e nem Spring. A versão do meu hibernate é 3.6.
Estou compartilhando o meu código para quem quiser copiar sem necessidade de referenciar origem.

Grande abraço e fiquem com Deus.

Ademir

public class SessionFactoryUtil {

	private static final SessionFactory sessionFactory;

	static {
		try {
			sessionFactory = new Configuration().configure().buildSessionFactory();
		} catch (Throwable e) {
			GravaLogErro.SalvarLogErro(e, "SessionFactoryUtil - Inicialização do SessionFactory");
			throw new ExceptionInInitializerError(e);
		}
	}

	public static SessionFactory getSessionFactory() {
		return sessionFactory;
	}

}
public final class HibernateSessionUtil {
	
	public HibernateSessionUtil() {	
				
	}

	public static Session getSession() {  
		return SessionFactoryUtil.getSessionFactory().getCurrentSession();
	}
	
	public static boolean isOpen() {
		return getSession().isOpen();
	}
	
	public static boolean inTransaction() {
		return getSession().getTransaction().isActive();
	}

	public static void beginTransaction() {
		if (!inTransaction())
			getSession().beginTransaction();
	}

	public static void commitTransaction() {
		if (inTransaction())
			getSession().getTransaction().commit();
	}

	public static void rollbackTransaction() {
		if (inTransaction())
			getSession().getTransaction().rollback();
	}

}
public class HibernateSessionFilter implements Filter {

    private SessionFactory sf;
    
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        
        Session session;
        
        try {            
            session = sf.openSession();
            
            ManagedSessionContext.bind((org.hibernate.classic.Session) session);
            session.setFlushMode(FlushMode.AUTO);
            
            chain.doFilter(request, response);
                 
            session = ManagedSessionContext.unbind(sf);
            
            if (HibernateSessionUtil.inTransaction()) {
            	//Gravar Log de problema
            }
            
            try {
				if ((session != null) && (session.isOpen())) {					
					session.close();					
				} else {
					//Gravar Log de problema
				}
			} catch (Throwable e) {
				GravaLogErro.SalvarLogErro(e, "doFilter ERROR - CloseSession");
			}            
            
        } catch (Throwable t) {
            try {
            	GravaLogErro.SalvarLogErro(t, "doFilter ERROR");
            	if (HibernateSessionUtil.inTransaction()) {
            		HibernateSessionUtil.rollbackTransaction();
                }
            } catch (Throwable rbT) {
            	//Gravar Log de problema
            } 
            
            finally {               
                session = ManagedSessionContext.unbind(sf);
                session.close();
            }
            
            throw new ServletException(t);
        }
        
    }
    
    public void init(FilterConfig filterConfig) throws ServletException {
    	try {
    		sf = SessionFactoryUtil.getSessionFactory();
    	} catch (Throwable rbT) {
        	//Gravar Log de problema
        }	
    }
    
    public void destroy() {
    	
    }
    
}
public class GenericDAO<T> {

	private Class persistentClass;
	private Session session;

	protected GenericDAO(Class p_persistentClass) {
		session = HibernateSessionUtil.getSession();
		persistentClass = p_persistentClass;
	}

	public Session getSession() {
		return session;
	}

	public Class getPersistentClassLocal(){
		return persistentClass;
	}

	public void insert(T obj) throws Exception {
		session.save(obj);
		session.flush();
	}

	public void update(T obj) throws Exception {
		session.update(obj);
		session.flush();
	}

	public void saveOrUpdate(T obj) throws Exception {
		session.saveOrUpdate(obj);
		session.flush();
	}

	public void merge(T obj) throws Exception {
		session.saveOrUpdate(obj);
		session.flush();
	}

	public void delete(T obj) throws Exception {
		session.delete(obj);
		session.flush();
	}

	public Integer count(List<Criterion> criterion) throws Exception {
		Criteria criteria = session.createCriteria(persistentClass);

		for (Criterion c: criterion)
			criteria.add(c);

		criteria.setProjection(Projections.rowCount());
		return ((Integer) criteria.uniqueResult()).intValue();
	}

	public List<T> listAll(String fieldOrder, SortOrder sortOrder) throws Exception {
		String ord = ConstantesGerais.TIPOORDEMASC;
		if (sortOrder == SortOrder.DESCENDING)
			ord = ConstantesGerais.TIPOORDEMDESC;

		Criteria criteria = session.createCriteria(persistentClass);
		addOrder(criteria, fieldOrder, ord);
		return criteria.list();
	}

	public List<T> listAll(int first, int max, String fieldOrder, SortOrder sortOrder, List<Criterion> criterion) throws Exception {
		String ord = ConstantesGerais.TIPOORDEMASC;
		if (sortOrder == SortOrder.DESCENDING)
			ord = ConstantesGerais.TIPOORDEMDESC;

		Criteria criteria = session.createCriteria(persistentClass);
		addOrder(criteria, fieldOrder, ord);

		for (Criterion c: criterion)
			criteria.add(c);

		if (first != 0)
			criteria.setFirstResult(first - 1);

		if (max != 0)
			criteria.setMaxResults(max);

		return criteria.list();
	}

	public T findById(Long id) throws Exception {
		return (T) session.get(persistentClass, id);
	}

	public String findByColumn(Long id, String fieldReturn) throws Exception {
		Criteria criteria = session.createCriteria(persistentClass);
		criteria.add(Restrictions.eq(getFieldId(), id)).setProjection(Projections.property(fieldReturn));
		criteria.uniqueResult();
		if (criteria.uniqueResult() == null)
			return "";
		else
			return criteria.uniqueResult().toString();
	}

	public String findByColumnValue(String findColumn, Long findValue, String fieldReturn) throws Exception {
		Criteria criteria = session.createCriteria(persistentClass);
		criteria.add(Restrictions.eq(findColumn, findValue)).setProjection(Projections.property(fieldReturn));
		if (criteria.uniqueResult() == null)
			return "";
		else
			return criteria.uniqueResult().toString();
	}

	public List<T> findByCriteria(List<Criterion> criterion) throws Exception {
		Criteria criteria = session.createCriteria(persistentClass);

		if (criterion == null)
			return null;

		for (Criterion c: criterion)
			criteria.add(c);

		return criteria.list();
	}

	private Criteria addOrder(Criteria criteria, String fieldOrder, String ord) {
		if (!fieldOrder.isEmpty()) {
			if ((ord.toUpperCase().equals("ASC")) || (ord.isEmpty()))
				criteria.addOrder(Order.asc(fieldOrder));

			if (ord.toUpperCase().equals("DESC"))
				criteria.addOrder(Order.desc(fieldOrder));
		}
		return criteria;
	}

}

up

Pra quem está usando spring, conhecem o projeto spring-data? Chamava-se HADES e foi incorporado pelo Spring. Estou estudando ainda, e não sei se aquilo pode ser chamado de Repository (se é que a intenção foi vincular ao pattern da Domain Driven Design), mas me pareceu bem prático. Estou usando em um projeto e funciona direitim :slight_smile:

http://www.springsource.org/spring-data

Outra grande vantagem é que ele faz a abstração da tecnologia de persistência, que pode ser até bancos NoSQL, como MongoDB.

Normalmente, defino meu DAO como sendo uma interface, e crio uma classe de implementação para o mesmo.