Problema Hibernate

Olá pessoal, tô precisando de uma ajudinha aqui no Hibernate, olha só:
Dois objetos, um chamado Sistema e outro MenuSistema, sendo que um Sistema tem de 1 a N MenuSistema. (Estou usando o Oracle 10g)

Aqui está o mapeamento de Sistema.hbm.xml:

<hibernate-mapping>
    <class 
        name="gov.ce.ipmfor.model.sca.Sistema" 
        table="SISTEMA">
      <id name="codigo" column="CODIGO" type="int" unsaved-value="-1">         
		 <generator class="sequence">			
           <param name="sequence">SISTEMA_SEQ</param>
         </generator>		 
      </id>
	  <set name="menusistema" lazy="true" table="MENU_SISTEMA" inverse="true" cascade="all">
		<key column="sistema">
		   <!--column name="sistema"></column-->						
		</key>
		<one-to-many class="gov.ce.ipmfor.model.sca.MenuSistema"/>
	  </set>
      <property name="nome" column="NOME"/>
      <property name="descricao" column="COMENTARIO"/>
      <property name="status" column="SITUACAO"/>
      <property name="link" column="LINK"/>  	  
   </class>    
</hibernate-mapping>

Aqui o mapeamento de MenuSistema.hbm.xml

<hibernate-mapping>
	<class 
		name="gov.ce.ipmfor.model.sca.MenuSistema" 
		table="MENU_SISTEMA">
		<id name="codigo" column="CODIGO" type="int" unsaved-value="-1">
			<generator class="sequence">
           <param name="sequence">MENU_SISTEMA_SEQ</param>
         </generator>			
		</id>
		<many-to-one name="sistema"  
			column="SISTEMA" 
			not-null="true" 
			cascade="save-update" 
			class="gov.ce.ipmfor.model.sca.Sistema" 
			unique="true">
		</many-to-one>
		<!--property name="sistema" column="SISTEMA"/-->
		<property name="nome" column="DESCRICAO"/>	
		<property name="link" column="LINK"/>	
        <property name="situacao" column="SITUACAO"/> 		
	</class>
</hibernate-mapping>

Aqui um Trecho do meu arquivo SistemaDAO.java:

...
Sistema s = new Sistema();
List sistemas = new ArrayList(); 
Criteria criteria = (Criteria) session.createCriteria(s.getClass()).addOrder(Order.asc("nome"))
            .setFirstResult(0)
            .setMaxResults(10);
            sistemas = criteria.list();
            //teste com a listagem de sistemas
            if (sistemas.size() != 0) {
                for (Iterator i = sistemas.iterator(); i.hasNext();){
                    s = (Sistema) i.next();
                    System.out.println("sistema: "+ s.getNome());
                    Set menu = (Set) s.getMenuSistema();
                    if (menu != null) {
                        if (menu.size() != 0) {
                            for (Iterator iter = menu.iterator(); iter.hasNext();){
                                if (iter.next() instanceof MenuSistema){
                                    System.out.println("menu: "+((MenuSistema) i.next()).getNome());//é aqui onde dispara a exceção
                                }
                            }
                        } else {
                            System.out.println("sistema não tem menus");
                        }
                    }
                }
            }

Olha só o que acontece:

Hibernate: select * from ( select this_.CODIGO as CODIGO0_, this_.NOME as NOME6_0_, this_.COMENTARIO as COMENTARIO6_0_, this_.SITUACAO as SITUACAO6_0_, this_.LINK as LINK6_0_ from SISTEMA this_ order by this_.NOME asc ) where rownum <= ?
sistema: Almoxarifado
Hibernate: select menusistem0_.sistema as sistema1_, menusistem0_.CODIGO as CODIGO1_, menusistem0_.CODIGO as CODIGO0_, menusistem0_.SISTEMA as SISTEMA7_0_, menusistem0_.DESCRICAO as DESCRICAO7_0_, menusistem0_.LINK as LINK7_0_, menusistem0_.SITUACAO as SITUACAO7_0_ from MENU_SISTEMA menusistem0_ where menusistem0_.sistema=?
sistema não tem menus
sistema: Previdência
Hibernate: select menusistem0_.sistema as sistema1_, menusistem0_.CODIGO as CODIGO1_, menusistem0_.CODIGO as CODIGO0_, menusistem0_.SISTEMA as SISTEMA7_0_, menusistem0_.DESCRICAO as DESCRICAO7_0_, menusistem0_.LINK as LINK7_0_, menusistem0_.SITUACAO as SITUACAO7_0_ from MENU_SISTEMA menusistem0_ where menusistem0_.sistema=?
sistema não tem menus
sistema: Recursos Humanos
Hibernate: select menusistem0_.sistema as sistema1_, menusistem0_.CODIGO as CODIGO1_, menusistem0_.CODIGO as CODIGO0_, menusistem0_.SISTEMA as SISTEMA7_0_, menusistem0_.DESCRICAO as DESCRICAO7_0_, menusistem0_.LINK as LINK7_0_, menusistem0_.SITUACAO as SITUACAO7_0_ from MENU_SISTEMA menusistem0_ where menusistem0_.sistema=?
sistema não tem menus
sistema: Saúde
Hibernate: select menusistem0_.sistema as sistema1_, menusistem0_.CODIGO as CODIGO1_, menusistem0_.CODIGO as CODIGO0_, menusistem0_.SISTEMA as SISTEMA7_0_, menusistem0_.DESCRICAO as DESCRICAO7_0_, menusistem0_.LINK as LINK7_0_, menusistem0_.SITUACAO as SITUACAO7_0_ from MENU_SISTEMA menusistem0_ where menusistem0_.sistema=?
sistema não tem menus
sistema: Suporte
Hibernate: select menusistem0_.sistema as sistema1_, menusistem0_.CODIGO as CODIGO1_, menusistem0_.CODIGO as CODIGO0_, menusistem0_.SISTEMA as SISTEMA7_0_, menusistem0_.DESCRICAO as DESCRICAO7_0_, menusistem0_.LINK as LINK7_0_, menusistem0_.SITUACAO as SITUACAO7_0_ from MENU_SISTEMA menusistem0_ where menusistem0_.sistema=?
(hibernate.LazyInitializationException 19  ) illegal access to loading collection
org.hibernate.LazyInitializationException: illegal access to loading collection
	at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:172)
	at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:48)
	at org.hibernate.collection.PersistentSet.hashCode(PersistentSet.java:324)
	at org.apache.commons.lang.builder.HashCodeBuilder.append(HashCodeBuilder.java:392)
	at org.apache.commons.lang.builder.HashCodeBuilder.reflectionAppend(HashCodeBuilder.java:353)
	at org.apache.commons.lang.builder.HashCodeBuilder.reflectionHashCode(HashCodeBuilder.java:327)
	at org.apache.commons.lang.builder.HashCodeBuilder.reflectionHashCode(HashCodeBuilder.java:194)
	at gov.ce.ipmfor.model.sca.BaseObject.hashCode(BaseObject.java:27)
	at gov.ce.ipmfor.model.sca.Sistema.hashCode(Sistema.java:144)
	at org.apache.commons.lang.builder.HashCodeBuilder.append(HashCodeBuilder.java:392)
	at org.apache.commons.lang.builder.HashCodeBuilder.reflectionAppend(HashCodeBuilder.java:353)
	at org.apache.commons.lang.builder.HashCodeBuilder.reflectionHashCode(HashCodeBuilder.java:327)
	at org.apache.commons.lang.builder.HashCodeBuilder.reflectionHashCode(HashCodeBuilder.java:194)
	at gov.ce.ipmfor.model.sca.BaseObject.hashCode(BaseObject.java:27)
	at gov.ce.ipmfor.model.sca.MenuSistema.hashCode(MenuSistema.java:131)
	at java.util.HashMap.put(Unknown Source)
	at java.util.HashSet.add(Unknown Source)
	at java.util.AbstractCollection.addAll(Unknown Source)
	at org.hibernate.collection.PersistentSet.endRead(PersistentSet.java:242)
	at org.hibernate.engine.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:183)
	at org.hibernate.engine.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:268)
	at org.hibernate.engine.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:249)
	at org.hibernate.loader.Loader.endCollectionLoad(Loader.java:554)
	at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:541)
	at org.hibernate.loader.Loader.doQuery(Loader.java:436)
	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:218)
	at org.hibernate.loader.Loader.loadCollection(Loader.java:1434)
	at org.hibernate.loader.collection.OneToManyLoader.initialize(OneToManyLoader.java:111)
	at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:488)
	at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:60)
	at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1430)
	at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:176)
	at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:48)
	at org.hibernate.collection.PersistentSet.size(PersistentSet.java:110)
	at gov.ce.ipmfor.dao.sca.SistemaDAO.getListBeans(SistemaDAO.java:95)
	at gov.ce.ipmfor.delegate.sca.SistemaDelegate.getListaSistemas(SistemaDelegate.java:120)
	at gov.ce.ipmfor.delegate.sca.SistemaDelegate.<init>(SistemaDelegate.java:60)
	at gov.ce.ipmfor.service.sca.loadListaSistemas.perform(loadListaSistemas.java:42)
	at org.apache.struts.action.ActionServlet.processActionPerform(ActionServlet.java:1619)
	at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1429)
	at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:462)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
	at com.opensymphony.module.sitemesh.filter.PageFilter.parsePage(PageFilter.java:118)
	at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
	at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
	at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
	at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
	at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
	at java.lang.Thread.run(Unknown Source)

Alguém pode me dar uma ajudinha aí? Agradeço antecipadamente a atenção.

Wagner

(“O Senhor é bom e a sua misericórdia dura para sempre”)

Estou fazendo uma pequena correção no SistemaDAO.java

... 
Sistema s = new Sistema(); 
List sistemas = new ArrayList(); 
Criteria criteria = (Criteria) session.createCriteria(s.getClass()).addOrder(Order.asc("nome")) 
            .setFirstResult(0) 
            .setMaxResults(10); 
            sistemas = criteria.list(); 
            //teste com a listagem de sistemas 
            if (sistemas.size() != 0) { 
                for (Iterator i = sistemas.iterator(); i.hasNext();){ 
                    s = (Sistema) i.next(); 
                    System.out.println("sistema: "+ s.getNome()); 
                    Set menu = (Set) s.getMenuSistema(); 
                    if (menu != null) { 
                        if (menu.size() != 0) { 
                            for (Iterator iter = menu.iterator(); iter.hasNext();){ 
                                if (iter.next() instanceof MenuSistema){ 
                                    System.out.println("menu: "+((MenuSistema) iter.next()).getNome());//CORREÇÃO                                } 
                            } 
                        } else { 
                            System.out.println("sistema não tem menus"); 
                        } 
                    } 
                } 
            } 

Mesmo assim o erro persiste.

Wagner

o problema esta aqui:

<set name="menusistema" lazy="true" table="MENU_SISTEMA" inverse="true" cascade="all"> <key column="sistema"> <!--column name="sistema"></column--> </key> <one-to-many class="gov.ce.ipmfor.model.sca.MenuSistema"/> </set>

mude para:

<set name="menusistema" lazy="false" table="MENU_SISTEMA" inverse="true" cascade="all"> <key column="sistema"> <!--column name="sistema"></column--> </key> <one-to-many class="gov.ce.ipmfor.model.sca.MenuSistema"/> </set>

mudamos o parametro “lazy” para false, assim quando vc carregar o seu objeto Sistema ele vai inicializar a colection automaticamente…mas tome cuidado, pq usar isso em varios lugares do seu mapeamento pode prejudicar muito a performance…

uma outra alterantiva é vc inicializar a colection sobre demanda…procure o metodo initialize() da classe Hibernate…

espero ter ajudado…

Valeu, cara…

Mas dentro dessa mesma abordagem, ainda tenho algumas dúvidas…

Suponha que eu crie uma instância de SistemaDAO em outra classe. Por exemplo:

  ...
  SistemaDAO sistemaDAO = new SistemaDAO();
  Sistema s = new Sistema();
  s = (Sistema) sistemaDAO.getBean(s.getCodigo());
  System.out.println("Nome do sistema é: "+ s.getNome());
  //até aqui tudo bem, mas na próxima instrução vai ocorrer uma exceção
  Set menusDesseSistema  = (Set) s.getMenuSistema();
  ...

Isso acontece por que a função getBeans(int id) de sistemaDAO, vai nessa ordem:

  • abrir uma Session do Hibernate;
  • iniciar uma Transaction;
  • recuperar um Sistema de código s.getCodigo();
  • fechar a Transaction.

Ou seja, mesmo que a referência ao Set esteja em sistema, ele não vai carregar o conjunto de menus, visto que não não há sessão aberta.

Foi aí que eu pensei em criar outro DAO só para carregar um objeto da classe MenuSistema, assim:

  ...
  SistemaDAO sistemaDAO = new SistemaDAO();
  Sistema s = new Sistema();
  s = (Sistema) sistemaDAO.getBean(s.getCodigo());
  MenuSistemaDAO menuDAO = new MenuSistemaDAO():
  Set menusDesseSistema  = (Set) menuDAO.getMenuSistema(s); //essa função recebe um objeto do tipo Sistema como parâmetro 
  ...

Gostaria de saber se essa mudança de estratégia seria correta. Se há uma melhor, agradeço antecipadamente se puder ajudar.

se vc setar o lazy como false, independente do seu controle transacional, vai funcionar…pq o Set eh inicializado sempre q vc popular a classe Sistema com os dados do banco…