-->
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.  [ 7 posts ] 
Author Message
 Post subject: LazyInitializationException with no relationship
PostPosted: Tue Sep 06, 2005 3:43 pm 
Beginner
Beginner

Joined: Thu Feb 03, 2005 10:42 pm
Posts: 30
I am generating LazyInitializationException when viewing data loaded on a hibernate loaded domain object that has no relationships at all. I am using hibernate 3 with spring. When I insert the explicit lazy="false" as an attribute to the class this goes away, but I don't understand why I am getting it in the first place. It must be something dumb but I assume you shouldn't have to set the lazy=false just to make it work by default and from what i read this should only affect relationships. Maybe I am misunderstanding the documentation.

Essentially in this test case I am trying to load data into a simple address object and display the toString view of that address pojo.

Here is my class definition:

Code:
<class name="mbs.test_newmodel.domainobjects.entities.Address" table="ADDRESS">
      <id name="id" column="ID" type="int" unsaved-value="-1" >
         <generator class="identity"/>
      </id>
      <property name="line1" column="LINE1" not-null="true"/>
      <property name="line2" column="LINE2"/>
      <property name="type" column="TYPE" not-null="true"/>
      <property name="city" column="CITY" not-null="true"/>
      <property name="state" column="STATE" not-null="true"/>
      <property name="postalCode" column="POSTAL_CODE" not-null="true"/>
      <property name="country" column="COUNTRY" not-null="true"/>
      <property name="companyId" column="COMPANY_ID" not-null="true"/>
   </class>





Here is my code where the error occurs:
Code:
DemographicsMgr demographicsMgr = (DemographicsMgr)    context.getBean("demographicsMgr");
Address address = demographicsMgr.getAddress(app.getUser().getDefaultCompanyId(), 1);
[b]System.err.println(address.toString());//**********ERROR OCCURS HERE[/b]


The getAddress method is implemented like so:

Code:
   public Address getAddress(int companyId, int addressId)
      {
         return addressDao.get(companyId, addressId);
      }


The implementation I am using in addressDao is as follows:

Code:
   public Address get(int companyId, int addressId)
      {
         return (Address)getHibernateTemplate().load(Address.class, new Integer(addressId));
      }

Full stack trace:

Code:
org.hibernate.LazyInitializationException: could not initialize proxy - the owning Session was closed
   at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:53)
   at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:84)
   at org.hibernate.proxy.CGLIBLazyInitializer.intercept(CGLIBLazyInitializer.java:134)
   at mbs.test_newmodel.domainobjects.entities.Address$$EnhancerByCGLIB$$eea99824.toString(<generated>)
   at mbs.test_newmodel.service.entities.DefaultDemographicsMgr.main(DefaultDemographicsMgr.java:101)


And if you want to see it here is my spring application context used for this test:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
   
   <!-- Data source bean -->
   <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
      <property name="driverClassName"><value>org.hsqldb.jdbcDriver</value></property>
      <property name="url"><value>jdbc:hsqldb:hsql://localhost:9001</value></property>
      <property name="username"><value>xxxxx</value></property>
      <property name="password"><value>xxxxxx</value></property>
   </bean>
               
   <bean id="phoneDao" class="mbs.test_newmodel.dao.implementations.hibernate.enitities.PhoneDao">
      <property name="sessionFactory"><ref local="sessionFactory"/></property>
   </bean>

   <bean id="addressDao" class="mbs.test_newmodel.dao.implementations.hibernate.enitities.AddressDao_Hibernate">
      <property name="sessionFactory"><ref local="sessionFactory"/></property>
   </bean>
   
   
   <bean id="demographicsMgr" class="mbs.test_newmodel.service.entities.DefaultDemographicsMgr">
      <property name="addressDao"><ref local="addressDao"/></property>
      <property name="phoneDao"><ref local="phoneDao"/></property>
   </bean>

   <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
      <property name="sessionFactory"><ref local="sessionFactory"/></property>
   </bean>
   
   <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
      <property name="dataSource"><ref local="dataSource"/></property>
      <property name="mappingResources">
         <list>
            <value>test.hbm.xml</value>
         </list>
      </property>
      <property name="hibernateProperties">
         <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
            <prop key="hibernate.max_fetch_depth">3</prop>
            <prop key="hibernate.show_sql">true</prop>
         </props>
      </property>
   </bean>
</beans>


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 06, 2005 11:06 pm 
Pro
Pro

Joined: Fri Sep 02, 2005 4:21 am
Posts: 206
Location: Vienna
Hi,

Starting with Hibernate 3 (AFAIK) lazy="true" is default. This means that getHibernateTemplate().load now returns a proxy - and this leads to the "friendly" LazyInitializationException if you continue to work.

Either use lazy="true" as you already did or use getHibernateTemplate().get instead (but of course the semantik is not exactly the same) - and alternative would be to use one transaction (i.e. Hibernate session in this case) over the related operations.

wexwarez wrote:
but I assume you shouldn't have to set the lazy=false just to make it work

In your use case you have to. But things are more subtle - as your example would work if your were within one transaction/Session.

wexwarez wrote:
Maybe I am misunderstanding the documentation.

You just oversaw the fine print ;-).

Hope this clarifies things a bit.

Erik


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 07, 2005 11:59 am 
Beginner
Beginner

Joined: Thu Feb 03, 2005 10:42 pm
Posts: 30
Honestly your reply confuses me a bit. Are you implying that I can't do the default lazy loading with spring? If you read my code you would see that I made a single call to load the data and then I simple display it's properties and that is where i get the exception. It doesn't seem right.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 07, 2005 12:05 pm 
Expert
Expert

Joined: Fri Aug 19, 2005 2:11 pm
Posts: 628
Location: Cincinnati
I've seen this too. getHibernateTemplate().find("... can give me a LazyInitializaitonException on columns of scalar values that aren't involving sets of other tables. I fixed it by making the class lazy="false" but that doesn't even make sense.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 07, 2005 2:04 pm 
Pro
Pro

Joined: Fri Sep 02, 2005 4:21 am
Posts: 206
Location: Vienna
Hi,

wexwarez wrote:
Honestly your reply confuses me a bit. Are you implying that I can't do the default lazy loading with spring? If you read my code you would see that I made a single call to load the data and then I simple display it's properties and that is where i get the exception. It doesn't seem right.

Sorry for that - it wasn't my intention.

The fact is that things are more complex that you seem to know.

If lazy is not set to false, the load method returns a proxy to the Address - without even accessing the database. The access to the database only occurs when you explicitly try to get data over that proxy. The problem is now that this access ends badly (with a LazyInitializationException) if you try to access the proxy in another session than the one where it was initially created.

Now comes Spring: if you use it "naively" it creates a session for each DAO access, which means that in your case you're exactly in the situation described above: the proxy is created and used in two different sessions...

The solutions I know are the ones I described. Maybe there is a simpler solution in Spring I'm not yet aware of. Fact is it took me quite a few hours of testing, reading and debugging to discover these "simple" facts...

So it is definitely possible to use lazy loading in Spring - together with transactions, and using transaction is a "good" thing :-).

To sum it up: there is more to Hibernate and Spring that one may be aware of at the beginning. But they're definitely usable and their complexity is simply a consequence of the complexity of what developer want to be able to achieve.

BTW: default setting of lazy was false in Hibernate 2.1, is true since 3.0. I don't know the rationale for this change, but it is a bit unexpected from my point of view.

I really hope I didn't confuse you even more...

Erik


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 07, 2005 2:14 pm 
Beginner
Beginner

Joined: Thu Feb 03, 2005 10:42 pm
Posts: 30
Erik-

I did notice the change of the default, that does seem odd. What you say makes sense. Spring essentially closes the session right after a call is made thus the proxy can't retrieve the object from the closed session.

However it is hard for me to believe that spring doesn't play nice with hibernate in it's default settings. Maybe there is a way in spring to tell it to keep the session open. I am inexperienced with both, but from the sounds of it if this is true it would disable all lazy loading capabilities of hibernate when working with spring.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 07, 2005 2:24 pm 
Pro
Pro

Joined: Fri Sep 02, 2005 4:21 am
Posts: 206
Location: Vienna
Hi,

wexwarez wrote:
However it is hard for me to believe that spring doesn't play nice with hibernate in it's default settings.

Spring plays nice insofar as it frees you from having to be concerned with Hibernate session issues for simple use cases.

When things get "tougher" (and they soon do) you have to know more about the frameworks you're using - it seems to me like a fact of life ;-).

Erik


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 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.