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

5 respostas
V

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.

/*
 * 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;
	}

}
Open Session In View
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() {}
 
}
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();
		}*/		
}

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

5 Respostas

R

Se você criou um filter, fecha no filter.

V

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!

V

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!

R

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

H

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

Criado 20 de novembro de 2012
Ultima resposta 20 de nov. de 2012
Respostas 5
Participantes 3