Announcement Announcement Module
Collapse
No announcement yet.
Failed to lazily initialize a collection - no Session Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Failed to lazily initialize a collection - no Session

    Hi,
    I am using Spring, Hibernate and Struts. Here is what I try to do:
    3 persisted classes:
    A --> (1-to-many) --> B --> (1-to-many)--> C

    All with cascade="all"

    In one Struts Action, I retrieve A and found that all B are retrieved automatically (I use A.getBs()). After which I put A into the request and forward to another Action.

    In the second Action, I try to get C (using B.getCs()) but got error message:
    -----------------------------------------------------------------------------
    18.09.04 12:18:44 [http8080-Processor25] DEBUG org.springframework.orm.hibernate.SessionFactoryUt ils - Opening Hibernate session
    18.09.04 12:18:44 [http8080-Processor25] DEBUG net.sf.hibernate.impl.SessionImpl - opened session
    18.09.04 12:18:44 [http8080-Processor25] DEBUG org.springframework.transaction.support.Transactio nSynchronizationManager - Bound value [org.springframework.orm.hibernate.SessionHolder@16 8be1b] for key [net.sf.hibernate.impl.SessionFactoryImpl@39d072] to thread [http8080-Processor25]
    18.09.04 12:18:44 [http8080-Processor25] DEBUG net.canal.core.action.BaseLookupAction - BaseAction: getLookupMapName( keyName = View )
    18.09.04 12:18:44 [http8080-Processor25] DEBUG net.canal.core.action.BaseLookupAction - BaseAction: getLookupMapName( keyName = Prepare )
    18.09.04 12:19:19 [http8080-Processor25] ERROR net.sf.hibernate.LazyInitializationException - Failed to lazily initialize a collection - no Session
    net.sf.hibernate.LazyInitializationException: Failed to lazily initialize a collection - no Session
    ------------------------------------------------------------------------------

    Does it mean that before forwarding to Action B, I need to retrieve C first ? I thought it should be transparent to me as the cascade is set to 'all' for these classes already.

    What do I misunderstood ?

    thanks in advance !

  • #2
    By the way, I have OpenSessionInView configured in web.xml:

    ----------------
    <filter>
    <filter-name>hibernateFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate.support.Op enSessionInViewFilter</filter-class>
    <init-param>
    <param-name>sessionFactoryBeanName</param-name>
    <param-value>canalSessionFactory</param-value>
    </init-param>
    </filter>

    <filter>
    <filter-name>ResponseOverrideFilter</filter-name>
    <filter-class>org.displaytag.filter.ResponseOverrideFilter </filter-class>
    </filter>

    <filter-mapping>
    <filter-name>securityFilter</filter-name>
    <url-pattern>/admin/*</url-pattern>
    </filter-mapping>

    <filter-mapping>
    <filter-name>hibernateFilter</filter-name>
    <url-pattern>*.do</url-pattern>
    </filter-mapping>

    ------------------------

    problem is still there.

    Comment


    • #3
      After which I put A into the request and forward to another Action.
      is this a server forward or are you using redirect?

      In the Action where you try to get C, you can rebind your entity to Hibernate Session before calling getCs() using
      Code:
          Session session = SessionFactoryUtils.getSession&#40;sessionFactory, false&#41;;
          session.lock&#40;B, LockMode.NONE&#41;;
      HTH

      Comment


      • #4
        I am using Struts Action forward, somethign like this:
        return (mapping.findForward("success"));

        The action manpping is something like this:
        <forward name="success" path=".createTemplateDef"/>

        which goes to a Tiles (.createTemplateDef).

        I suppose it is forward not redirect.

        I will try your suggetion.

        thanks

        Comment


        • #5
          has this approach ...

          worked for you?

          seems that we have the same problem ...
          made a similar post yesterday - maybe you can have a look at it

          thanx

          tuor

          Comment


          • #6
            I have a similar problem. In the first action it's possible to load a lazy collection after loading the parent, but loading the collection in another action does not work. What am I missing? I can see in the log that the filter is actually closing the session, or is the log-message just vague?

            DEBUG HibernateTransactionManager [http8080-Processor24] - Not closing pre-bound Hibernate session [net.sf.hibernate.impl.SessionImpl@1c81ac0] after transaction
            DEBUG OpenSessionInViewFilter [http8080-Processor24] - Closing single Hibernate session in OpenSessionInViewFilter
            DEBUG SessionFactoryUtils [http8080-Processor24] - Closing Hibernate session
            DEBUG SessionImpl [http8080-Processor24] - closing session
            DEBUG SessionImpl [http8080-Processor24] - disconnecting session
            DEBUG SessionImpl [http8080-Processor24] - transaction completion

            Comment


            • #7
              have not got time to try tuor's suggestion. I am busy with a few other things. really tired.

              but i still think it is a configuration problem if I understand the OpenSessionInView correctly.

              Comment


              • #8
                found the problem (I hope):

                1. when retrieving the parent object, OpenSessionInView creates a new session; SessionImpl is kept in the child collection

                2. in the next requst, OpenSessionInView will create another new session; when trying to get child collection, the previous session is used but not initialized so causing the problem.

                But i do not know how to fix the problem.

                Comment


                • #9
                  I tried 'singleSession' to 'true' but still the same problem. So it seems that it IS becuase the previous session is not initialized.

                  I will try the lock suggestion but in this case, 'lazy loading' only means I gain performace benifit the first time when I retrieve the parent obj. The code is messy if I have have to touch the hibernate session anywhere I need to access collections.

                  where is the bext place to put the lock method ?

                  is my understanding correct ?

                  Comment


                  • #10
                    I try the suggestion:

                    Session session = SessionFactoryUtils.getSession(sessionFactory, false);
                    session.lock(B, LockMode.NONE);


                    but it is still the same.

                    Before calling session.lock(), I can see that B has C info like this (I am using Eclipse IDE)
                    B--
                    additions=null
                    collectionSnapshot=SessionImpl$CollectionEntry (id=353)
                    directlyAccessible=false
                    initialized=false
                    initializing=false
                    session=SessionImpl (id=356)
                    set=null
                    tempList=null

                    After locking, the collectionSnapshot and session are all changed to a different id.

                    Then when I access Bs, I do get all the items - and also the initialized is changed to 'true'

                    But I am wondering if this is the right way to support the lazy loading:
                    1) I have to add this code in everywhere I need to access a lazily loaded collection
                    2) any performace issue by introducing this locking ?

                    thanks !

                    Comment


                    • #11
                      typo. the above solution works. but i am still trying to understand more and why OpenSessionInViewFilter plus lazy=true is not sufficient.

                      Comment


                      • #12
                        this is indeed weird !

                        The above solution only works if I step into my A.getBs() during debugging. If not, the 'initialized=false' will not be changed to 'initialized=true' hence I can not get any Bs.

                        here is my code:
                        ------

                        List aList = (List) request.getSession().getAttribute ("aList");
                        A a = aList.get(0);
                        try {
                        session.lock (a, LockMode.NONE);
                        } catch {
                        ....
                        }

                        Set b = (Set) a.getB(); //<====I have to step into this !!!

                        ......
                        ------

                        I am using Spring framework 1.1, Hibernate 2.1.6, Struts 1.1 and I am debugging in Eclipse 3.0.

                        Comment


                        • #13
                          Karl's weblog post explains this in further detail.

                          http://www.jroller.com/comments/kbau...ation_with_dao

                          Comment


                          • #14
                            I begin using Spring, and my example was this simple tutorial

                            However, it does not explain how to manage lazy collections.
                            I tried to apply the advices given in the Karl's weblog post, but as I encountered some problems.
                            Here is a part of my xml configuration file
                            Code:
                            <bean id="myTransactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
                            		<property name="sessionFactory"><ref local="mySessionFactory"/></property>
                            	</bean>
                            <bean id="userService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">	
                            		<property name="transactionManager"><ref local="myTransactionManager"/></property>
                            		<property name="target"><ref local="userTarget"/></property>			
                            		<property name="transactionAttributes">
                            			<props>
                            				<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
                            				<prop key="save*">PROPAGATION_REQUIRED</prop>
                            			</props>
                            		</property>
                            	</bean>
                            As you can see, I use TransactionProxyFactoryBean elements while Karl Baum uses ProxyFactoryBean.
                            The problem is that I cannot use the hibernateInterceptor as he does.

                            Any idea about how to adapt it ?
                            Thanks.

                            Comment

                            Working...
                            X