Failed to lazily initialize a collection

7 respostas
D

Pessoal
tenho uma classe que tem uma lista dentro dela

classe:

@Entity
@Table(schema = "assinatura", name = "GRUPO_DISTRIBUICAO")
@SequenceGenerator(name = "seq", sequenceName = "assinatura.SEQ_GRUPO", allocationSize = 1)
public class GrupoDistribuicao extends AbstractPojo {

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq")
	@Column(name = "COD_GRUPO_DISTRIBUICAO", precision = 4, scale = 0)
	private Long codGrupoDistribuicao;

	@Column(name = "NOME_GRUPO_DISTRIBUICAO", nullable = false, length = 30)
	private String nomeGrupoDistribuicao;

	@Column(name = "VALOR_PORTE", nullable = false, precision = 9, scale = 2)
	private Double valorPorte;

	@ManyToMany(fetch = FetchType.LAZY)
	@JoinTable(name = "GRUPO_DISTRIBUICAO_UF", schema = "assinatura", 
			joinColumns = @JoinColumn(name = "COD_GRUPO_DISTRIBUICAO"), 
			inverseJoinColumns = @JoinColumn(name = "COD_UF"))
	private Set<UF> ufs;

Quando eu executo esse método

public T findById(Long id) throws Exception {

		T result = null;
		Session session = null;
		Transaction transaction = null;

		try {

			session = HibernateUtil.getSession();
			transaction = session.beginTransaction();

			result = (T) session.get(refClass, id);

			transaction.commit();
		}
		catch (Exception e) {
			try {
				transaction.rollback();
			}
			catch (Exception ex) {
				ex.printStackTrace();
				throw ex;
			}
			e.printStackTrace();
			throw e;
		}
		
		return result;
	}

o erro acontece

Hibernate: 
    /* criteria query */ select
        this_.COD_GRUPO_DISTRIBUICAO as COD1_22_0_,
        this_.NOME_GRUPO_DISTRIBUICAO as NOME2_22_0_,
        this_.VALOR_PORTE as VALOR3_22_0_ 
    from
        assinatura.GRUPO_DISTRIBUICAO this_
failed to lazily initialize a collection of role: br.gov.in.assinatura.modulo.grupoDistribuicao.pojo.GrupoDistribuicao.ufs, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: br.gov.in.assinatura.modulo.grupoDistribuicao.pojo.GrupoDistribuicao.ufs, no session or session was closed
	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
	at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:365)
	at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
	at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:186)
	at org.apache.struts.taglib.logic.IterateTag.doStartTag(IterateTag.java:267)
	at org.apache.jsp.WEB_002dINF.jsp.modulos.grupoDistribuicao.listGrupoDistribuicoes_jsp._jspService(listGrupoDistribuicoes_jsp.java:217)
	at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
	at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:630)
	at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:535)
	at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:472)
	at org.apache.jasper.runtime.JspRuntimeLibrary.include(JspRuntimeLibrary.java:968)
	at org.apache.jasper.runtime.PageContextImpl.doInclude(PageContextImpl.java:640)
	at org.apache.jasper.runtime.PageContextImpl.include(PageContextImpl.java:634)
	at sun.reflect.GeneratedMethodAccessor41.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:585)
	at org.apache.struts.tiles.TilesUtilImpl.doInclude(TilesUtilImpl.java:129)
	at org.apache.struts.tiles.TilesUtil.doInclude(TilesUtil.java:152)
	at org.apache.struts.tiles.taglib.InsertTag.doInclude(InsertTag.java:764)
	at org.apache.struts.tiles.taglib.InsertTag$InsertHandler.doEndTag(InsertTag.java:896)
	at org.apache.struts.tiles.taglib.InsertTag.doEndTag(InsertTag.java:465)
	at org.apache.jsp.WEB_002dINF.jsp.layout.baseLayout_jsp._jspx_meth_tiles_005finsert_005f2(baseLayout_jsp.java:441)
	at org.apache.jsp.WEB_002dINF.jsp.layout.baseLayout_jsp._jspService(baseLayout_jsp.java:133)
	at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
	at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:630)
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:436)
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374)
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
	at org.apache.struts.tiles.commands.TilesPreProcessor.doForward(TilesPreProcessor.java:260)
	at org.apache.struts.tiles.commands.TilesPreProcessor.execute(TilesPreProcessor.java:217)
	at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:191)
	at org.apache.commons.chain.generic.LookupCommand.execute(LookupCommand.java:305)
	at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:191)
	at org.apache.struts.chain.ComposableRequestProcessor.process(ComposableRequestProcessor.java:283)
	at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
	at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:449)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at br.gov.in.assinatura.kernel.sca.NavegacaoPrincipalFiltro.doFilter(NavegacaoPrincipalFiltro.java:152)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
	at java.lang.Thread.run(Thread.java:595)

Alguem sabe pq isso?
eu não entendo, se colocar EAGER, ai funciona tudo certinho
o problema que pesa minha aplicação.
Alguem sabe resolver esse problema ?
é alguma configuração de hibernate etc?

7 Respostas

D

ninguem nunca passou por isso

F

Se não quiser usar EAGER, então em cada consulta vc precisa acordar o relacionamento.
Se estiver usando Criteria, vc deve usar essa função.

public Criteria setFetchMode(String associationPath, FetchMode mode) throws HibernateException;

E mais docs sobre isso
http://docs.jboss.org/hibernate/stable/core/reference/en/html/performance.html

B

Esse erro ocorre quando você define uma Collection (List, Set etc) com fetchmode lazy e tenta acessar esse atributo após ter fechado a sessão do hibernate ou após esse objeto ter passado para o estado detached.
Sugiro que você utilize crie um filtro na tua servlet que abra e feche a sessão do Hibernate, garantindo que ela esteja sempre disponível durante todo o lifecycle da app.

Saca só:

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;

public class HibernateSessionFilter implements Filter {

	public void destroy() {
		// TODO Auto-generated method stub

	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain filterChain) throws IOException, ServletException {
		HibernateUtil.openSession();
		try {
			HibernateUtil.currentSession().beginTransaction();
			filterChain.doFilter(request, response);
			HibernateUtil.currentSession().getTransaction().commit();
		} catch (Exception e) {
			throw new ServletException(e);
		} finally {
			HibernateUtil.closeCurrentSession();
		}
		
	}

	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub

	}

}

E o HibernateUtil:

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

public class HibernateUtil {

	private static SessionFactory sessionFactory;
	private static ThreadLocal<Session> sessions = new ThreadLocal<Session>();
	
	static {
		AnnotationConfiguration configuration = new AnnotationConfiguration();
		configuration.configure();
		sessionFactory = configuration.buildSessionFactory();
	}
	
	public static Session openSession(){
		Session session = sessionFactory.openSession();
		sessions.set(session);
		return sessions.get();
	}
	
	public static Session currentSession(){
		return sessions.get();
	}
	
	public static void closeCurrentSession(){
		sessions.get().close();
		sessions.set(null);
	}
	
	public static void clearSession(){
		sessions.get().clear();
	}
	
	public static void flushSession(){
		sessions.get().flush();
	}
	
	public static void rollback(){
		sessions.get().getTransaction().rollback();
		sessions.get().getTransaction().begin();
	}
	
}
B

Ah! Se o teu objeto saiu do managed e foi pro detached state, só dar um update no objeto que resolve.
Mas recomendo dar um merge antes, para evitar a exception de redundância no cache do hibernate!

P

Olá bronx,

O exemplo de filtro que você deu foi muito útil para um problema que estava arrancando meus cabelos.

Obrigado

Abraço :smiley:

P

se sua appweb tiver Spring, no web.xml tem um filtro que vc coloca pra sessao do hibernate continuar aberta pra nao dar esse erro… so nao lembro qual mas eh uma dica de start…

B

Legal, Thiago.

É essencial entender esse lance dos estados do Hibernate.

A documentação do Hibernate é riquíssima, vale muito a pena gastar um tempo no site deles lendo-a! =D

Criado 18 de setembro de 2009
Ultima resposta 10 de fev. de 2012
Respostas 7
Participantes 5