Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: Problem with transaction org.hibernate.LazyInitializationException:

  1. #1
    Join Date
    Aug 2009
    Posts
    12

    Default Problem with transaction org.hibernate.LazyInitializationException:

    Hi All,
    I am trying to configure spring, hibernate and enable spring transaction.
    After going through documents and examples i have done a simple setup with parent child entity relation. This particular setup works fine for single entity without any relation, but in the case of parent child relation it fails to load the child entity. I have used the hibernate API to code the DAO class.
    Transaction closes before the related entity is fetched. I have set lazy="true", if i change to false every thig works fine. Kindly find the attachment for stacktrace.


    org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: no session or session was closed

    Code:
    ///DataSource
    
    	<bean id="_dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
    		<property name="url" value="jdbc:mysql://192.100.1.1/testdb" />
    		<property name="username" value="user" />
    		<property name="password" value="pass" />
    	</bean>
    
    //Session factory
    
    	<bean id="_sessionFactory"
    		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    		<property name="dataSource" ref="_dataSource" />
    		<property name="mappingResources">
    
    			<list>
    				<value>resources/ParentChild.hbm.xml
    				</value>
    			</list>
    		</property>
    		<property name="hibernateProperties">
    			<value>hibernate.dialect=org.hibernate.dialect.MySQLDialect
    				hibernate.current_session_context_class=thread</value>
    		</property>
    	</bean>
    
    	<bean id="parentDao" class="com.gts.sample.dao.ParentDAOHibernate">
    		<property name="sessionFactory" ref="_sessionFactory"></property>
    	</bean>
    
    //Transaction
    
    	<bean id="txManager"
    		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    		<property name="sessionFactory" ref="_sessionFactory" />
    	</bean>
    
    
    	<bean id="rowSampleService"
    		class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    		<property name="transactionManager" ref="txManager" />
    		<property name="target">
    			<bean class="com.gts.sample.service.RowSampleService">
    				<property name="dao" ref="parentDao" />
    			</bean>
    		</property>
    		<property name="transactionAttributes">
    			<props>
    				<prop key="*">PROPAGATION_REQUIRED</prop>
    			</props>
    		</property>
    
    	</bean>
    
    
    //hbm///
    <hibernate-mapping>
    	<class name="com.gts.sample.service.Parent" table="parent">
    		<id name="parentId" type="integer" column="PARENT_ID">
    			<generator class="native" />
    		</id>
    		<set name="childrenDetails" cascade="save-update" order-by="CHILD_ID" lazy="false" >
    			<key column="PARENT_ID" not-null="true" />
    			<one-to-many class="com.gts.sample.service.Child" />
    		</set>
    		<property name="parentName" column="PARENT_NAME" type="string" />
    		<property name="isEnabled" column="IS_ENABLED" type="yes_no" />
    		<property name="isDeleted" column="IS_DELETED" type="yes_no" />
    	</class>
    
    
    	<class name="com.gts.sample.service.Child" table="child">
    		<id name="childId" type="integer" column="CHILD_ID">
    			<generator class="native" />
    		</id>
    		<property name="childName" column="CHILD_NAME" type="string" />
    		<property name="isEnabled" column="IS_ENABLED" type="yes_no" />
    		<property name="isDeleted" column="IS_DELETED" type="yes_no" />
    	</class>
    
    </hibernate-mapping>
    
    //DAO
    public class ParentDAOHibernate implements ParentDAO {
    
    	private SessionFactory sessionFactory;
    
    	public Session getSession() {
    		System.out.println("getting session from factory==>>");
    		return this.sessionFactory.getCurrentSession();
    	}
    
    	public void setSessionFactory(SessionFactory sessionFactory) {
    		System.out.println("setting sessionFactory==>>");
    		this.sessionFactory = sessionFactory;
    	}
    
    	public Parent findById(Integer fk) {
    		Parent entity = (Parent) getSession().load(Parent.class, fk);
    		Hibernate.initialize(entity);
    		return entity;
    	}
    }
    //Service
    public class RowSampleService extends BaseService  {
    
    	public void setDao(ParentDAO dao) {
    		this.dao = dao;
    	}
    
    	public ParentDAO getDao() {
    		return (ParentDAO) this.dao;
    	}
    
    	public Parent getChildWithParent(Integer pk) {
    		Parent parent = (Parent) dao.findById(pk);
    	//	System.out.println(parent); // works fine if sop uncommented
    		return parent;
    	}
    
    }
    
    
    ///////Test
    
    public static void main(String... strings) {
    		String[] source = new String[] {
    				"WebContent/WEB-INF/config/spring-hibernate.xml",
    				"WebContent/WEB-INF/config/application-context.xml",
    				"WebContent/WEB-INF/config/Row-crud-sample.xml" };
    
    		ApplicationContext context = new FileSystemXmlApplicationContext(source);
    		IRowSampleService service = (IRowSampleService) context
    				.getBean("rowSampleService");
    		System.out.println(service.getChildWithParent(1));
    
    	}
    Attached Files Attached Files

  2. #2
    Join Date
    Feb 2006
    Posts
    20

    Default

    It's because you're calling toString() method on entity. Your BaseDomain.toString() method implementation is using Apache's ReflectionToStringBuilder which is trying to print all entity properties.

    Since your collection is mapped with lazy = "true" and session is already closed this means Hibernate does not know how to fetch elements of this collection.

  3. #3
    Join Date
    Aug 2009
    Posts
    12

    Default

    Quote Originally Posted by rience View Post
    It's because you're calling toString() method on entity. Your BaseDomain.toString() method implementation is using Apache's ReflectionToStringBuilder which is trying to print all entity properties.

    Since your collection is mapped with lazy = "true" and session is already closed this means Hibernate does not know how to fetch elements of this collection.
    Brilliant … thanks a lot…. I removed the overridden toString() method from the basedomain and it worked great. I am curious to know how you pin pointed the issue?
    Thanks again.
    Vijay

  4. #4
    Join Date
    Feb 2006
    Posts
    20

    Default

    Just by looking through stack trace. I think it's rather common problem (I also experienced one of these some time ago).

  5. #5
    Join Date
    Aug 2009
    Posts
    12

    Default

    Quote Originally Posted by rience View Post
    I think it's rather common problem (I also experienced one of these some time ago).
    Is there any hibernate compatible toString() method available?

  6. #6
    Join Date
    Feb 2006
    Posts
    20

    Default

    Well, you can always initialize collection in transaction before returning from method. Or not use ReflectionToStringBuilder - just ToStringBuilder, specifying exactly which properties you want to print out.

  7. #7
    Join Date
    Aug 2009
    Posts
    12

    Default

    Still i have the issue... I get the same exception if i loop through collection.. where i am wrong

    Test
    Code:
    Parent p = service.getChildWithParent(1);
    
    		for (Child child : p.getChildrenDetails()) {
    			System.out.println(child.getChildName());
    		}

    Stacktrace
    Code:
    main TransactionSynchronizationManager.getResource - <Retrieved value [org.springframework.orm.hibernate3.SessionHolder@2c35e] for key [org.hibernate.impl.SessionFactoryImpl@1687e7c] bound to thread [main]>
    main TransactionAspectSupport.doCommitTransactionAfterReturning - <Invoking commit for transaction on com.gts.sample.service.IRowSampleService.getChildWithParent>
    main AbstractPlatformTransactionManager.triggerBeforeCommit - <Triggering beforeCommit synchronization>
    main AbstractPlatformTransactionManager.triggerBeforeCompletion - <Triggering beforeCompletion synchronization>
    main AbstractPlatformTransactionManager.commit - <Initiating transaction commit>
    main HibernateTransactionManager.doCommit - <Committing Hibernate transaction on session [org.hibernate.impl.SessionImpl@955cd5]>
    main AbstractPlatformTransactionManager.triggerAfterCompletion - <Triggering afterCompletion synchronization>
    main TransactionSynchronizationManager.clearSynchronization - <Clearing transaction synchronization>
    main TransactionSynchronizationManager.unbindResource - <Removed value [org.springframework.orm.hibernate3.SessionHolder@2c35e] for key [org.hibernate.impl.SessionFactoryImpl@1687e7c] from thread [main]>
    main TransactionSynchronizationManager.unbindResource - <Removed value [org.springframework.jdbc.datasource.ConnectionHolder@8ceeea] for key [org.apache.commons.dbcp.BasicDataSource@1060478] from thread [main]>
    Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.gts.sample.service.Parent.childrenDetails, no session or session was closed
    	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
    	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
    	at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
    	at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
    	at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:163)
    	at com.gts.sample.service.TestRowSample.getTest(TestRowSample.java:36)
    	at com.gts.sample.service.TestRowSample.main(TestRowSample.java:44)
    main HibernateTransactionManager.doCleanupAfterCompletion - <Closing Hibernate session [org.hibernate.impl.SessionImpl@955cd5] after transaction>
    main SessionFactoryUtils.doClose - <Closing Hibernate Session>
    main LazyInitializationException.<init> - <failed to lazily initialize a collection of role: com.gts.sample.service.Parent.childrenDetails, no session or session was closed>
    org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.gts.sample.service.Parent.childrenDetails, no session or session was closed
    	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
    	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
    	at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
    	at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
    	at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:163)
    	at com.gts.sample.service.TestRowSample.getTest(TestRowSample.java:36)
    	at com.gts.sample.service.TestRowSample.main(TestRowSample.java:44)

  8. #8
    Join Date
    Feb 2006
    Posts
    20

    Default

    I'm not sure where are your transaction boundaries. If transaction boundaries are on getChildWithParent() method - then you need to initialize nested collection inside this method. As soon as code exits it - your session is closed.

  9. #9
    Join Date
    Sep 2006
    Location
    UK
    Posts
    8,424

    Default

    Quote Originally Posted by vijaykmr View Post
    Is there any hibernate compatible toString() method available?
    It's probably not a good idea to use this toString as well, as you really don't want lazy collections to always be loaded. Just specify only simple properties which aren't going to require another fetch.
    Barracuda Networks SSL VPN Lead Developer
    http://pramatr.wordpress.com
    http://twitter.com/karldmoore
    http://www.linkedin.com/in/karldmoore
    Any postings are my own opinion, and should not be attributed to my employer or clients.

  10. #10
    Join Date
    Aug 2009
    Posts
    12

    Default

    Quote Originally Posted by rience View Post
    I'm not sure where are your transaction boundaries. If transaction boundaries are on getChildWithParent() method - then you need to initialize nested collection inside this method. As soon as code exits it - your session is closed.
    I am able to figure out the issue...
    i have set transaction boundaries to business object (rowSampleService), but i access the entity and its collection in my test class. As the entity are not Initialized It throws exception. I tried adding this but the child entity are not initialized.
    Code:
    entity = (T) getSession().load(getPersistentClass(), id);
    Hibernate.initialize(entity);
    // In brief
    Basically I am trying to use TransactionManager (with AOP) instead of OpenSessionInViewFilter for displaying domain object in presentation. As hibernate session ends in Service layer I am unable to load the related entity in presentation. How to design this scenario?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •