Announcement Announcement Module
Collapse
No announcement yet.
cannot access loading collection Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • cannot access loading collection

    I have a basic many to many relationship between users and roles. When I assign a role to a user and save the user everything works fine and the association is persisted to the user_role table. However, when I try to load the user I get a lazyInitializationException when hibernate tries to initialize my roles collection. I'm sure i'm missing something obvious here but can't figure it out.

    My hbm.xml files for each entity are as follows:

    <hibernate-mapping>

    <class name="au.com.groupware.model.User" table="USER">
    <meta attribute="extends">BaseObject</meta>
    <id name="userId" column="USER_ID" type="java.lang.Long" unsaved-value="null">
    <generator class="increment" />
    </id>
    <property name="userName" column="USER_NAME" type="java.lang.String" not-null="true" length="50" />
    <property name="firstName" column="FIRST_NAME" type="java.lang.String" not-null="true" length="50" />
    <property name="lastName" column="LAST_NAME" type="java.lang.String" not-null="true" length="50" />
    <property name="email" column="EMAIL" type="java.lang.String" not-null="true" length="50" />
    <property name="password" column="PASSWORD" type="java.lang.String" not-null="true" length="50" />

    <set name="roles" table="USER_ROLE" lazy="false" cascade="all">
    <key column="USER_ID" />
    <many-to-many class="au.com.groupware.model.Role" column="ROLE_ID" />
    </set>
    </class>

    </hibernate-mapping>

    <hibernate-mapping>

    <class name="au.com.groupware.model.Role" table="ROLE">
    <meta attribute="extends">BaseObject</meta>
    <id name="roleId" column="ROLE_ID" type="java.lang.Long" unsaved-value="null">
    <generator class="increment" />
    </id>
    <property name="roleName" column="ROLE_NAME" type="java.lang.String" not-null="true" length="50" />
    <property name="description" column="DESCRIPTION" type="java.lang.String" not-null="true" length="255" />
    <set name="users" table="USER_ROLE" inverse="true" lazy="false">
    <key column="ROLE_ID" />
    <many-to-many class="au.com.groupware.model.User" column="USER_ID" />
    </set>
    </class>

    </hibernate-mapping>



    I have a spring transaction wrapper around my DAO's and for the moment lazy is set to false. I'm farily sure it must be something to do with my mappings because it's the single getUser() method that is failing. whenever any roles are assigned in the database for a user.

    The getUser method is simply:

    public User getUser(Long userId) {
    return (User) getHibernateTemplate().get(User.class, userId);
    }
    the relevent part of the log with Spring set to debug is:



    DEBUG - TransactionInterceptor.invoke(168) | Getting transaction for method 'getUser' in class [au.com.groupware.service.UserManager]
    DEBUG - AbstractPlatformTransactionManager.getTransaction( 163) | Using transaction object [org.springframework.orm.hibernate.HibernateTransac tionObject@52fda6]
    DEBUG - AbstractPlatformTransactionManager.getTransaction( 214) | Creating new transaction
    DEBUG - SessionFactoryUtils.getSession(183) | Opening Hibernate session
    DEBUG - HibernateTransactionManager.doBegin(271) | Opened new session [net.sf.hibernate.impl.SessionImpl@8adb01] for Hibernate transaction
    DEBUG - HibernateTransactionManager.doBegin(280) | Beginning Hibernate transaction on session [net.sf.hibernate.impl.SessionImpl@8adb01]
    INFO - DriverManagerDataSource.getConnectionFromDriverMan ager(152) | Creating new JDBC connection to [jdbc:mysql://localhost:3306/groupware?autoReconnect=true]
    DEBUG - HibernateTransactionManager.doBegin(292) | Setting JDBC connection [com.mysql.jdbc.Connection@302723] read-only
    DEBUG - TransactionSynchronizationManager.bindResource(141 ) | Bound value [org.springframework.orm.hibernate.SessionHolder@15 97115] for key [net.sf.hibernate.impl.SessionFactoryImpl@75a43c] to thread [http-80-Processor24]
    DEBUG - TransactionSynchronizationManager.bindResource(141 ) | Bound value [org.springframework.jdbc.datasource.ConnectionHold er@10f30f5] for key [org.springframework.jdbc.datasource.DriverManagerD ataSource@147239c] to thread [http-80-Processor24]
    DEBUG - TransactionSynchronizationManager.initSynchronizat ion(192) | Initializing transaction synchronization
    DEBUG - TransactionSynchronizationManager.getResource(117) | Retrieved value [org.springframework.orm.hibernate.SessionHolder@15 97115] for key [net.sf.hibernate.impl.SessionFactoryImpl@75a43c] bound to thread [http-80-Processor24]
    ERROR - LazyInitializationException.<init>(25) | cannot access loading collection
    net.sf.hibernate.LazyInitializationException: cannot access loading collection
    at net.sf.hibernate.collection.PersistentCollection.i nitialize(PersistentCollection.java:191)
    at net.sf.hibernate.collection.PersistentCollection.r ead(PersistentCollection.java:71)
    at net.sf.hibernate.collection.Set.hashCode(Set.java: 383)
    at org.apache.commons.lang.builder.HashCodeBuilder.ap pend(HashCodeBuilder.java:392)
    at org.apache.commons.lang.builder.HashCodeBuilder.re flectionAppend(HashCodeBuilder.java:353)
    at org.apache.commons.lang.builder.HashCodeBuilder.re flectionHashCode(HashCodeBuilder.java:327)
    at org.apache.commons.lang.builder.HashCodeBuilder.re flectionHashCode(HashCodeBuilder.java:194)
    at au.com.groupware.model.BaseObject.hashCode(BaseObj ect.java:28)
    at org.apache.commons.lang.builder.HashCodeBuilder.ap pend(HashCodeBuilder.java:392)
    at org.apache.commons.lang.builder.HashCodeBuilder.re flectionAppend(HashCodeBuilder.java:353)
    at org.apache.commons.lang.builder.HashCodeBuilder.re flectionHashCode(HashCodeBuilder.java:327)
    at org.apache.commons.lang.builder.HashCodeBuilder.re flectionHashCode(HashCodeBuilder.java:194)
    at au.com.groupware.model.BaseObject.hashCode(BaseObj ect.java:28)
    at java.util.HashMap.hash(HashMap.java:261)
    at java.util.HashMap.put(HashMap.java:379)
    at java.util.HashSet.add(HashSet.java:192)
    at java.util.AbstractCollection.addAll(AbstractCollec tion.java:319)
    at net.sf.hibernate.collection.Set.endRead(Set.java:2 44)
    at net.sf.hibernate.impl.SessionImpl.endLoadingCollec tions(SessionImpl.java:3073)
    at net.sf.hibernate.impl.SessionImpl.endLoadingCollec tions(SessionImpl.java:3060)
    at net.sf.hibernate.loader.Loader.doQuery(Loader.java :243)
    at net.sf.hibernate.loader.Loader.doQueryAndInitializ eNonLazyCollections(Loader.java:133)
    at net.sf.hibernate.loader.Loader.loadCollection(Load er.java:915)
    at net.sf.hibernate.loader.Loader.loadCollection(Load er.java:890)
    at net.sf.hibernate.loader.OneToManyLoader.initialize (OneToManyLoader.java:93)
    at net.sf.hibernate.collection.AbstractCollectionPers ister.initialize(AbstractCollectionPersister.java: 284)
    at net.sf.hibernate.impl.SessionImpl.initializeCollec tion(SessionImpl.java:3259)
    at net.sf.hibernate.collection.PersistentCollection.f orceInitialization(PersistentCollection.java:336)
    at net.sf.hibernate.impl.SessionImpl.initializeNonLaz yCollections(SessionImpl.java:3114)
    at net.sf.hibernate.loader.Loader.doQueryAndInitializ eNonLazyCollections(Loader.java:138)
    at net.sf.hibernate.loader.Loader.loadEntity(Loader.j ava:836)
    at net.sf.hibernate.loader.Loader.loadEntity(Loader.j ava:856)
    at net.sf.hibernate.loader.EntityLoader.load(EntityLo ader.java:59)
    at net.sf.hibernate.loader.EntityLoader.load(EntityLo ader.java:51)
    at net.sf.hibernate.persister.EntityPersister.load(En tityPersister.java:419)
    at net.sf.hibernate.impl.SessionImpl.doLoad(SessionIm pl.java:2106)
    at net.sf.hibernate.impl.SessionImpl.doLoadByClass(Se ssionImpl.java:1980)
    at net.sf.hibernate.impl.SessionImpl.get(SessionImpl. java:1916)
    at org.springframework.orm.hibernate.HibernateTemplat e$1.doInHibernate(HibernateTemplate.java:181)
    at org.springframework.orm.hibernate.HibernateTemplat e.execute(HibernateTemplate.java:150)
    at org.springframework.orm.hibernate.HibernateTemplat e.get(HibernateTemplate.java:179)
    at au.com.groupware.dao.hibernate.UserDAOHibernate.ge tUser(UserDAOHibernate.java:31)
    at au.com.groupware.service.impl.UserManagerImpl.getU ser(UserManagerImpl.java:39)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:324)
    at org.springframework.aop.framework.AopProxyUtils.in vokeJoinpointUsingReflection(AopProxyUtils.java:59 )
    at org.springframework.aop.framework.ReflectiveMethod Invocation.invokeJoinpoint(ReflectiveMethodInvocat ion.java:149)
    at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :118)
    at org.springframework.transaction.interceptor.Transa ctionInterceptor.invoke(TransactionInterceptor.jav a:191)
    at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :138)
    at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:148)
    at $Proxy38.getUser(Unknown Source)
    at au.com.groupware.web.action.UserAction.edit(UserAc tion.java:85)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:324)
    at org.apache.struts.actions.DispatchAction.dispatchM ethod(DispatchAction.java:309)
    at org.apache.struts.actions.DispatchAction.execute(D ispatchAction.java:231)
    at org.springframework.web.struts.DelegatingActionPro xy.execute(DelegatingActionProxy.java:131)
    at org.apache.struts.action.RequestProcessor.processA ctionPerform(RequestProcessor.java:449)
    at org.apache.struts.action.RequestProcessor.process( RequestProcessor.java:264)
    at org.apache.struts.action.ActionServlet.process(Act ionServlet.java:1176)
    at org.apache.struts.action.ActionServlet.doGet(Actio nServlet.java:454)
    at javax.servlet.http.HttpServlet.service(HttpServlet .java:689)
    at javax.servlet.http.HttpServlet.service(HttpServlet .java:802)
    at org.apache.catalina.core.ApplicationFilterChain.in ternalDoFilter(ApplicationFilterChain.java:237)
    at org.apache.catalina.core.ApplicationFilterChain.do Filter(ApplicationFilterChain.java:157)
    at org.springframework.orm.hibernate.support.OpenSess ionInViewFilter.doFilterInternal(OpenSessionInView Filter.java:117)
    at org.springframework.web.filter.OncePerRequestFilte r.doFilter(OncePerRequestFilter.java:73)
    at org.apache.catalina.core.ApplicationFilterChain.in ternalDoFilter(ApplicationFilterChain.java:186)
    at org.apache.catalina.core.ApplicationFilterChain.do Filter(ApplicationFilterChain.java:157)
    at com.opensymphony.module.sitemesh.filter.PageFilter .parsePage(PageFilter.java:142)
    at com.opensymphony.module.sitemesh.filter.PageFilter .doFilter(PageFilter.java:58)
    at org.apache.catalina.core.ApplicationFilterChain.in ternalDoFilter(ApplicationFilterChain.java:186)
    at org.apache.catalina.core.ApplicationFilterChain.do Filter(ApplicationFilterChain.java:157)
    at org.apache.catalina.core.StandardWrapperValve.invo ke(StandardWrapperValve.java:214)
    at org.apache.catalina.core.StandardValveContext.invo keNext(StandardValveContext.java:104)
    at org.apache.catalina.core.StandardPipeline.invoke(S tandardPipeline.java:520)
    at org.apache.catalina.core.StandardContextValve.invo keInternal(StandardContextValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invo ke(StandardContextValve.java:152)
    at org.apache.catalina.core.StandardValveContext.invo keNext(StandardValveContext.java:104)
    at org.apache.catalina.authenticator.AuthenticatorBas e.invoke(AuthenticatorBase.java:462)
    at org.apache.catalina.core.StandardValveContext.invo keNext(StandardValveContext.java:102)
    at org.apache.catalina.core.StandardPipeline.invoke(S tandardPipeline.java:520)
    at org.apache.catalina.core.StandardHostValve.invoke( StandardHostValve.java:137)
    at org.apache.catalina.core.StandardValveContext.invo keNext(StandardValveContext.java:104)
    at org.apache.catalina.valves.ErrorReportValve.invoke (ErrorReportValve.java:118)
    at org.apache.catalina.core.StandardValveContext.invo keNext(StandardValveContext.java:102)
    at org.apache.catalina.core.StandardPipeline.invoke(S tandardPipeline.java:520)
    at org.apache.catalina.core.StandardEngineValve.invok e(StandardEngineValve.java:109)
    at org.apache.catalina.core.StandardValveContext.invo keNext(StandardValveContext.java:104)
    at org.apache.catalina.core.StandardPipeline.invoke(S tandardPipeline.java:520)
    at org.apache.catalina.core.ContainerBase.invoke(Cont ainerBase.java:929)
    at org.apache.coyote.tomcat5.CoyoteAdapter.service(Co yoteAdapter.java:160)
    at org.apache.coyote.http11.Http11Processor.process(H ttp11Processor.java:799)
    at org.apache.coyote.http11.Http11Protocol$Http11Conn ectionHandler.processConnection(Http11Protocol.jav a:705)
    at org.apache.tomcat.util.net.TcpWorkerThread.runIt(P oolTcpEndpoint.java:577)
    at org.apache.tomcat.util.threads.ThreadPool$ControlR unnable.run(ThreadPool.java:683)
    at java.lang.Thread.run(Thread.java:534)

    any ideas ?

  • #2
    From the looks of it your app is based off Matt Raible's AppFuse or something similar, where there is a base object which by default uses the Apache commons-lang reflection based approach to producing the equals and hashCode methods.

    That base class is actually somewhat dangerous as-is. There's nothing wrong with using the manual helper classes in comoons-lang, but the reflection-0based stuff is going to hit every field in your class. In this case, Hibernate is deciding to call hashCode, and then that ends up trying to access the collection, when it's not yet initialized I guess.

    Just create your own equals and hashCode methods (including only relevant fields), and I think your problem will go away...

    Comment


    • #3
      Many thanks Colin...You're right, i'm using a mixture of Equinox and appFuse as the basis for this app. I have modified my persistent classes so they no longer extend BaseObject and everything seems to be fine now so thanks!

      Now i'm onto my second problem which seems to be stumping a number of people on this forum... When I set Lazy="true" for my collections I get the standard lazy initialization error. I am aware that this is due to the session being opened and closed by my transactionManager which means i can no longer access the collection of roles for the user outside the DAO methods. I have setup an openSessionInView filter as suggested in other posts but for some reason a new session is always opened by my DAOs. I can see the session opening once in the view, again inside the DAO, close on terminiation of that transaction and then again at the end of the request.

      Is there something obvious I might be missing that tells my transaction manager to user the existing session rather than create a new one ?

      Comment


      • #4
        I've since moved away from using these methods in BaseObject and the next release has custom equals() and hashCode() methods in each object. For rapid generation of these, I'm recommending folks use Commonclipse:

        http://commonclipse.sourceforge.net/

        Seems to work pretty well so far.

        Comment


        • #5
          cheers Matt. thanks for the update.

          Comment


          • #6
            Just a note that people should still be very careful about how they set up their equals and hashCode methods, since it is not legal for the hash to change once an object is added to a collection. If the object does not have a separate synthetic key for persistence, and a business key (i.e. username for example) for equality/hash usage, and you are using persistence engine generated keys (as is possible with Hibernate), you are violating the hashCode() contract. One inefficient solution is to always use a non-changing hashCode():
            return getClass().hashCode();
            this will work but will turn a HashMap into a list. With Hibernate, the best solution is to go to separate keys for persistence and for equality/hashing, or never store the object in a collection until the id has been generated...

            Comment


            • #7
              As always, Spring forums are more useful than any other, thanks a lot!
              After I read this thread, I could get rid of that "cannot access loading collection" exception.
              I did the following to get rid of it, how do you think, is it still dangerous or is it safe now?
              I defined my collection in the parent class as transient(I have a one-to-many assoc.)
              Code:
              private transient Set children = new HashSet&#40;&#41;;
              And the hashCode method of my base class:
              Code:
              public int hashCode&#40;&#41; &#123;    	
                  return HashCodeBuilder.reflectionHashCode&#40;this, false&#41;;
              &#125;
              The "false" as the second parameter tells not to include transient fields in the hashCode calculation.

              For equals, there is a similar method which I found to be safe:
              Code:
              reflectionEquals&#40;Object lhs, Object rhs, boolean testTransients&#41;
              Thanks,
              Turgay Zengin

              Comment

              Working...
              X