Dúvida quanto a Open Session In View e session.close();

Olá, pessoal, tudo bem?

Estou tendo problemas com minha aplicação quando dou um session.load no objeto!
Minha dúvida é o seguinte? Onde eu devo fechar minha sessão? No meu DAO, no meu Filter ? ou no meu Hibernate Util.

[code]/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */
    package util;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
private static ThreadLocal threadlocal = new ThreadLocal();
private static SessionFactory sessionFactory = new Configuration()
.configure().buildSessionFactory();

public HibernateUtil() {
	// TODO Auto-generated constructor stub
}

public static Session getSession() {
	Session session = (Session) threadlocal.get();
	if (session == null) {
		session = sessionFactory.openSession();			
		threadlocal.set(session);
	}
	return session;
}

public void begin() {
	getSession().beginTransaction();

}

public void commit() {
	getSession().getTransaction().commit();
}

public void rollback() {
	getSession().getTransaction().rollback();
}

public void close() {
	getSession().close();
}

public static void shutdown() {
	// Close caches and connection pools
	getSessionFactory().close();
}

// passamos ele para o Filter
public static SessionFactory getSessionFactory() {
	return sessionFactory;
}

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

}[/code]

Open Session In View

[code]package filter;
import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.SessionFactory;
import org.hibernate.StaleObjectStateException;

import util.HibernateUtil;

@WebFilter("/*")
public class HibernateSessionRequestFilter implements Filter {

private static Log log = LogFactory.getLog(HibernateSessionRequestFilter.class);

private SessionFactory sf;

public void doFilter(ServletRequest request,
                     ServletResponse response,
                     FilterChain chain)
        throws IOException, ServletException {

    try {
        log.debug("Starting a database transaction");
        sf.getCurrentSession().beginTransaction();

        // Call the next filter (continue request processing)
        chain.doFilter(request, response);

        // Commit and cleanup
        log.debug("Committing the database transaction");
        sf.getCurrentSession().getTransaction().commit();            

    } catch (StaleObjectStateException staleEx) {
        log.error("This interceptor does not implement optimistic concurrency control!");
        log.error("Your application will not work until you add compensation actions!");            
        throw staleEx;
    } catch (Throwable ex) {            
        ex.printStackTrace();
        try {
            if (sf.getCurrentSession().getTransaction().isActive()) {
                log.debug("Trying to rollback database transaction after exception");
                sf.getCurrentSession().getTransaction().rollback();
            }
        } catch (Throwable rbEx) {
            log.error("Could not rollback transaction after exception!", rbEx);
        } 
        
        throw new ServletException(ex);
    }
}

public void init(FilterConfig filterConfig) throws ServletException {
    log.debug("Initializing filter...");
    log.debug("Obtaining SessionFactory from static HibernateUtil singleton");
    sf = HibernateUtil.getSessionFactory();
}

public void destroy() {}

}[/code]

[code]public class UFDaoImp implements UFDao, Serializable {

/**
 * 
 */
private static final long serialVersionUID = 1L;	


@SuppressWarnings("unchecked")
@Override
public List<UF> list() throws BusinessException {
	Session session = HibernateUtil.getSessionFactory().openSession();
	Transaction t = session.beginTransaction();
	try {
		List<UF> lista = session.createQuery("from UF").list();
		t.commit();
		return lista;
	} catch (Exception e) {
		t.rollback();
		throw new BusinessException(
				"Erro no banco de dados! Contacte o Administrador!");
	} finally {
		session.close();
	}

}

@Override	
public UF getUF(Integer idUF) throws BusinessException {
	Session session = HibernateUtil.getSessionFactory().openSession();
	try {			
		return (UF) session.load(UF.class, idUF);
	} catch (Exception e) {			
		throw new BusinessException(
				"Erro no banco de dados! Contacte o Administrador!");
	}/*finally {
		
		session.close();
	}*/		

}
[/code]

Desta forma, se eu fecho a sessão aí, dá a conhecida lazy exception!

Se você criou um filter, fecha no filter.

Olá romarcio, obrigado pela resposta!

Minha dúvida é o seguinte, como eu vou pegar essa session no dao?
Abrindo essa sessão no filter, como eu passaria ela pro dao?

Todos os exemplos que eu vi, nenhum fechava a sessão na view, e estranhamente, nenhum continha o modo de acesso a Session no dao!

Outra coisa que eu esqueci de falar é que eu utilizo o AJAX praticamente em todo CRUD. Na mesma página eu faço a inserção, exclusão, listagem e atualização. Então, se eu fecho a conexão no método de listagem por exemplo, ele dá erro, porque a página já está renderizada!

Eu sou obrigado a fechar a session, ou se eu deixar ela aberta o próprio java fecha?
Nessa abordagem, acho que o filtro não está fazendo muito efeito, já que ele só se faz útil antes da pagina ser renderizada.

A opção que eu estou vendo é deixar a session aberta, deste modo o problema não ocorre, ou então mudar pra EAGER, fato que eu não queria!

Da uma olhada nesse tutorial http://blog.camilolopes.com.br/opensessionviewsolucao/

O código da sua classe filter parece o mesmo.

Se for, no tutorial ele demonstra uma classe genérica DAO, utilize essa classe e estenda ela nas suas classes especificas de DAO. Assim você vai ter acesso ao DAO dentro de suas classes especificas.

Quando você usa getCurrentSession(), você não precisa fechar a sessão, o hibernate controla isso para você.

De uma lida na referencia: http://docs.jboss.org/hibernate/orm/3.5/reference/pt-BR/html/tutorial.html

Aqui mostra soluções para o seu problema de lazy: Quatro soluções para LazyInitializationException.