Lazily initialize collection JSF+SPring+JPA

17 respostas
leonardobhbr

Boa noite galera estou com um problema em ao carregar minha lista de entity no datatable quando tem uma relação 1 para N está dando a seguinte mensagem

failed to lazily initialize a collection of role: br.com.crm.orm.entity.Categoria.produtoCollection, no session or session was closed

Se alguem puder me ajudar agradeço

17 Respostas

furutani

Mantenha a session aberta enquanto você trabalha com as com os objetos.

jcmird

Colocar EAGER no relacionamento dependendo da necessidade o desempenho é melhor que o LAZY.

leonardobhbr

Vlw funcionou com EAGER

Lavieri

EAGER é perigoso…

pode fazer vc puxar dados de + atoa

leonardobhbr

É eu percebir nao pude colocar EAGER pois ta dando erro no hibernate quando todos estao EAGER
da o erro

cannot simultaneously fetch multiple bags

Alguem tem alguma solução pro meu problema, pois na hora que eu vou jogar no datatable a sessão ja está fechada

Lavieri

não feche a sessão ^^

a outra opção é antes de fechar a sessão invocar os métodos lazy que vc vai utilizar

leonardobhbr

Mais eu não fecho a sessão o spring que gerencia isso pra mim

E

estou com o mesmo problema !!! já pesquisei e adicionei o filtro OpenSessionInViewFilter na aplicação mas continua acontecendo!!!

leonardobhbr

No meu web.xml adicionei isso aqui

<!--  Filter OpenSession 
  --> 
- <filter>
  <filter-name>openEntityManager</filter-name> 
  <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class> 
  </filter>
- <filter-mapping>
  <filter-name>openEntityManager</filter-name> 
  <url-pattern>/*</url-pattern> 
  </filter-mapping>
- <!--  Filter OpenSession 
  -->

Resoveu para 90% dos casos quando mesmo assim não funciona infelizmente no metodo que eu carrego a minha lista de produtos por exemplo, no mesmo metodo e do size na minha collection que esta dentro do produto só para obrigar o hibernate carregar a lista.

Espero ter ajudado

A

Estou com o mesmo problema!

Como eu faço para não fechar a sessão?

Vlw

D

apalmeira:
Estou com o mesmo problema!

Como eu faço para não fechar a sessão?

Vlw


Use o mesmo que o amigo acima configurou mas, delegue as transações para o Spring. Desta forma, não terá problemas como o colega acima citou.

A

Eu não utilizo o Spring, somente jsf e jpa.

LPJava

eu conseguir resolver com esse post: http://community.jboss.org/wiki/OpenSessioninView é o melhor que temos, e resolve mesmo, 10min tinha tudo resolvido. estou usando hibernate + jsf com o tipo do elemento LAZY. Mudar para EAGER so se for ultima opcao.

A

Obrigado!

Poderia postar a classe HibernateUtil e a HibernateSessionRequestFilter? Não sei se entendi direito, mas me parece que são só essas duas mesmo, estou certo?

Estou com alguns problemas no sistema da empresa, e ainda estou aprendendo jpa/hibernate. Para ser sincero estou com bastante dificuldades para utilizar o Lazy e o pool de conexoes.

Vou começar um curso de hibernate na Caelum no próximo mes, o problema é que tenho que apresentar um modulo do sistema para um cliente, e sem o Lazy fica mto lento.

Valeu

A

Olá,

Encontrei esse exemplo aqui no Guj!

Nesse caso a pessoa utiliza o Hibernate e retona um sessionFactory. O que eu devo retornar com o JPA?

Outra coisa, preciso alterar alguma coisa nas minhas classes? hoje eu faço assim:

EntityManagerProvider

public class EntityManagerProvider {

    private static EntityManagerFactory emf = null;
    private static EntityManagerFactory emfOracle = null;
    private static EntityManagerFactory emfBysoft = null;

    private EntityManagerProvider()   
    {         
    }   
       
    public static EntityManagerFactory getEntityManagerFactory()
    {
        if (emf == null)
        {
            emf = Persistence.createEntityManagerFactory("JayBird");
        }
        return emf;
    }   

    
}

Managed Bean

EntityManagerFactory emf = EntityManagerProvider.getEntityManagerFactory();
    EntityManager em = emf.createEntityManager();
    em.getTransaction().begin();
    ......

Exemplo localizado no Guj:

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 {   
            sf.getCurrentSession().beginTransaction();   
            chain.doFilter(request, response);   
            sf.getCurrentSession().getTransaction().commit();   
        } catch (StaleObjectStateException staleEx) {   
            throw staleEx;   
        } catch (Throwable ex) {   
  
            ex.printStackTrace();   
            try {   
                if (sf.getCurrentSession().getTransaction().isActive()) {   
                    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.getInstace().getSessionFactory();   
        sf.openSession();   
    }   
  
    public void destroy() {}   
  
    public boolean isLoggable(LogRecord record) {   
        throw new UnsupportedOperationException("Not supported yet.");   
    }   
  
}
public class HibernateUtil {   
    private static HibernateUtil me;   
    private SessionFactory sessionFactory;   
    public HibernateUtil() {   
          sessionFactory = new AnnotationConfiguration().configure("hibernate.cfg.xml").buildSessionFactory();   
    }   
    public Session getSession(){           
        Session toReturn = sessionFactory.openSession();   
        //toReturn.beginTransaction();   
        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;   
    }   
}
LPJava
apalmeira:
Obrigado!

Poderia postar a classe HibernateUtil e a HibernateSessionRequestFilter? Não sei se entendi direito, mas me parece que são só essas duas mesmo, estou certo?

Estou com alguns problemas no sistema da empresa, e ainda estou aprendendo jpa/hibernate. Para ser sincero estou com bastante dificuldades para utilizar o Lazy e o pool de conexoes.

Vou começar um curso de hibernate na Caelum no próximo mes, o problema é que tenho que apresentar um modulo do sistema para um cliente, e sem o Lazy fica mto lento.

Valeu

bem, esse HibernateUtil é a na verdade a fábrica de session, no meu caso ele fica dentro de um DAO generico. Vou postar o meu código de teste que implementei antes de ir colocar na aplicacao real veja:
package br.com.filtro;
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 org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.SessionFactory;
import org.hibernate.StaleObjectStateException;

import br.com.dao.DAO;
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 {
	          System.out.println("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!");
	            // Rollback, close everything, possibly compensate for any permanent changes
	            // during the conversation, and finally restart business conversation. Maybe
	            // give the user of the application a chance to merge some of his work with
	            // fresh data... what you do here depends on your applications design.
	            throw staleEx;
	        } catch (Throwable ex) {
	            // Rollback only
	            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);
	            }
	 
	            // Let others handle it... maybe another interceptor for exceptions?
	            throw new ServletException(ex);
	        }
	    }
	 
	    public void init(FilterConfig filterConfig) throws ServletException {
	        //log.debug("Initializing filter...");
	       // log.debug("Obtaining SessionFactory from static HibernateUtil singleton");
	        sf = DAO.getSessionfactory();
	    }
	 
	    public void destroy() {}
	  
}
DAO
package br.com.dao;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class DAO {
	private static final SessionFactory sessionfactory = new Configuration().configure().
	buildSessionFactory();
	private static final ThreadLocal threadlocal = new ThreadLocal(); 
	
	public DAO() {
	
	}
	
	public static Session getSession(){
		Session session = (Session) threadlocal.get();
		if(session==null){
			session = sessionfactory.openSession();
			threadlocal.set(session);
		}
		return session; 
	}
flw!
A

Obrigado,

mais uma coisa, esse DAO também funciona para JPA ou só para Hibernate?

Hoje eu faço isso:

private static EntityManagerFactory emf = null;
       
    public static EntityManagerFactory getEntityManagerFactory()
    {
        if (emf == null)
        {
            emf = Persistence.createEntityManagerFactory("JayBird");
        }
        return emf;
    }

MB

EntityManagerFactory emf = EntityManagerProvider.getEntityManagerFactory();
    	    EntityManager em = emf.createEntityManager();
    	    em.getTransaction().begin();

e pego o EntityManagerFactory nos MBs, no seu arquivo você utiliza o SessionFactory! Eu poderia utilizar o EntityManagerFactory ou deveria usar outra coisa?

Vlw

Criado 11 de abril de 2009
Ultima resposta 21 de abr. de 2010
Respostas 17
Participantes 8