-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: Lazy Loading
PostPosted: Wed May 17, 2006 3:58 pm 
Newbie

Joined: Fri Mar 24, 2006 5:10 pm
Posts: 7
I apologize in advance if this question has been asked before. I assure you that I have been looking and could have overlooked the answer.

That said, I am using spring 1.2.7, hibernate 3.1, and annotations 3.1beta8.

I have two collections that I wish to load only upon demand. I am trying desperately to get it working so that I stop getting the LazyInitializationException.

My spring setup looks like this:

<bean name="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
....
</bean>

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="retrieversDataSource"/>
</bean>

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
<property name="transactionInterceptor" ref="txInterceptor"/>
</bean>

<bean id="txInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="txManager"/>
<property name="transactionAttributeSource">
<bean class="org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"/>
</property>
</bean>


I used the annotation @Transactional on a method to effectively run the method in a transaction:

Here is the method:

@Transactional
public List<ComponentParm> getComponentParms( final JavaComponent javaComponent ) {
return (List<ComponentParm>)hibernateTemplate.executeFind(
new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
return javaComponent.getParms();
}
} );
}

The getParms method is the one that fails. My thinking, and I know I'm off here, is that I am running in a transaction, and I've acquired a session by using the hibernate template.

I've tried other ways, but this is the best I can come up with, and I am stuck. I traced into SessionFactoryUtils.doGetSession, and no matter my @Transactional annotation, I always get a fresh session, which is probably another problem, but none of this behaves like I expect.

If there is some documentation that explains by example, this would be greatly appreciated. I am stuck.

Again, I apologize, but I am new to this, and nobody here knows the answer.

Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 19, 2006 4:07 am 
Expert
Expert

Joined: Sat Oct 25, 2003 8:49 am
Posts: 490
Location: Vrhnika, Slovenia
Quote:
Thanks for the help people, but I won't be back.


Hmmmm .... :-)

Ok, seriously now.
I don't think this is the right forum to ask this - since this is plain Spring usage case - no EJB3 stuff in sight.

Anway, here's a little help.
I think you are using the wrong kind of TransactionManager.

When I used Hibernate with Spring I used this kind of xml stuff:
Code:
    <bean id="hibernateTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>

    <!-- basic hibernate dao -->

    <bean id="basicDAOImpl" class="com.gl.ecos.data.dao.HibernateBasicDAO">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
        <property name="rootModuleId"><value>1</value></property>
    </bean>

    <bean id="basicDAO" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager"><ref local="hibernateTransactionManager"/></property>
        <property name="target"><ref local="basicDAOImpl"/></property>
        <property name="transactionAttributes">
            <props>
                <prop key="find*">PROPAGATION_SUPPORTS,readOnly</prop>
                <prop key="load*">PROPAGATION_SUPPORTS,readOnly</prop>
                <prop key="save*">PROPAGATION_REQUIRED</prop>
                <prop key="delete*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>



Ok, this is the old way - no annotations involved in classes on methods.

But most important stuff - in what way are you using this?
Where does the exception fail, is this web stuff, Swing client, ...


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 19, 2006 7:03 am 
Newbie

Joined: Fri Mar 24, 2006 5:10 pm
Posts: 7
I knew I would get busted! My need for help overshadowed my pride. Thanks for getting past it.

I've kind of got this working. I was getting a LazyInitiationException when trying to access the collection property from the parent object. The collection was set to load lazily.

I wasn't operating in a transaction because the method I set to Transactional was not in a bean loaded by Spring, so it wasn't wrapped. I fixed that and still had the problem.

Then I found a thread about locking the object to the hibernate session. So I did that and it fixed it in some cases. I'm not sure why I got it to work sometimes but not others, but I think I know. I wrote a method wrapped in a transaction that first acquired the object, locked the parent to the session, then returned the collection. Here is that method:

public List<ComponentParm> getComponentParms( final JavaComponent javaComponent ) {
return (List<ComponentParm>)hibernateTemplate.executeFind(
new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
session.lock( javaComponent, LockMode.NONE );
List<ComponentParm> parms = javaComponent.getParms();
return parms;
}
} );
}

Basically I'm passing the parent object to the method, locking it, then returning the collection. This doesn't always work though, and I still get the collection back as having an error lazily loading.

So, in the end, I went to the getter of the collection in JavaComponent and inserted a call to collection.getSize(), and now the collection is loaded every time and correctly. This defeats the purpose of lazy loading, since in effect I'm loading the collections every time, but I'm at wits end here. I'd like to get it working right, but I'll accept working in some form.

By the way, this is in a web application, but also accessible from plain ole java applications. Right now I'm testing from a test program until it works.


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 19, 2006 7:08 am 
Newbie

Joined: Fri Mar 24, 2006 5:10 pm
Posts: 7
I meant to say that I am accessing the size() method of the collection in the collection setter method, to force loading of the collection.


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 19, 2006 7:19 am 
Expert
Expert

Joined: Sat Oct 25, 2003 8:49 am
Posts: 490
Location: Vrhnika, Slovenia
Quote:
I knew I would get busted! My need for help overshadowed my pride. Thanks for getting past it.


Yep ... hehe .. :-) ... NP!


There are two ways you can do this.

Get a Session instance opened before 1. method call, use Spring or SessionFactory.getCurrentSession to stick it to your thread (or transaction if you're using JTA), then use it in 1. method, with proper usage you will also get the same session instance in 2. method, than at the end close that session instance.

Or like you already tried - with locking parent object in 2. method - but you have to have proper cascade on your wanted association / child.

As mentioned before:
- look at CurrentSessionContext usage in SessionFactoryImpl
- OpenSessionInViewInterceptor.java or OpenSessionInViewFilter.java

Rgds, Ales


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 19, 2006 8:32 am 
Newbie

Joined: Fri Mar 24, 2006 5:10 pm
Posts: 7
I appear to have it worked out. I modified the supplied method to access a property of the collection so that it would load, so I am using lazy loading. I added a property to the parent to determine if the collection was loaded yet or not, to avoid calling this lazy session initializer twice.

I'm not sure why I have to do this. I would think hibernate would recognize that I am accessing the collection in the getter and have that be enough of a trigger, but the getter might be invoked internally by hibernate making that untenable. I don't know, but I think I'm in the clear.

Thanks for replying, and for being a sport.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.