Announcement Announcement Module
Collapse
No announcement yet.
LazyInitializationException question. Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • LazyInitializationException question.

    We just started to work with Spring and Spring data and are getting a LazyInitializationException. I tried to read as much as aI can about Transactional, but I am somewhat lost. think I am missing something obvious but I can find it. Could someone please help. When running my code I get a org.hibernate.LazyInitializationException. This is due to EntityManager being closed. I tried to add @Transactional but that did not help. I create a repository, fetch the data and display it all in the same function, yet I still get the exception.

    The bean (Person) has an id (\@Id) and list of friends (List<Friend> with \@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE) When accessing the list it throws an exception.

    The repository
    Code:
    public interface PersonDAO extends PagingAndSortingRepository<Person, String> { }
    The bean class
    Code:
    @Entity
    public class Person {
    	@Id
    	public String id;
    	@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
    	public List<Person> friends;
    
    	public Person() {
    		id = UUID.randomUUID().toString();
    		friends = new ArrayList<Person>();
    	}
    }
    Main code
    Code:
    	@Transactional
    	private static void readNoManager(String id) {
    		PersonDAO personDAO = context.getBean(PersonDAO.class);
    		Person p = personDAO.findOne(id);
    		System.out.println(p.friends.size());		
    	}
    The exception
    Code:
    22:23:18,137 DEBUG  org.springframework.orm.jpa.JpaTransactionManager: 593 - Closing JPA EntityManager [org.hibernate.ejb.EntityManagerImpl@263e53cf] after transaction
    22:23:18,137 DEBUG .springframework.orm.jpa.EntityManagerFactoryUtils: 343 - Closing JPA EntityManager
    22:23:18,138 DEBUG bernate.engine.jdbc.internal.LogicalConnectionImpl: 314 - Releasing JDBC connection
    22:23:18,138 DEBUG bernate.engine.jdbc.internal.LogicalConnectionImpl: 332 - Released JDBC connection
    22:23:18,138 DEBUG .engine.jdbc.internal.proxy.ConnectionProxyHandler: 219 - HHH000163: Logical connection releasing its physical connection
    Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: edu.illinois.ncsa.Person.friends, no session or session was closed
    	at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:393)
    	at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:385)
    	at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:125)
    	at org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:242)
    	at edu.illinois.ncsa.Main.readNoManager(Main.java:48)
    	at edu.illinois.ncsa.Main.main(Main.java:19)
    my applicationContext.xml
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    	xmlns:jpa="http://www.springframework.org/schema/data/jpa"
        xmlns:tx="http://www.springframework.org/schema/tx"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
    		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    		http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
    
    	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    		<property name="dataSource" ref="dataSource" />
    		<property name="jpaVendorAdapter">
    			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    				<property name="generateDdl" value="true" />
    			</bean>
    		</property>
    		<property name="packagesToScan">
    			<list>
    				<value>edu.illinois.ncsa</value>
    			</list>
    		</property>
    	</bean>
    
    
    	<!-- Translates Hibernate exceptions to Spring Data Access Exceptions -->
    	<bean class="org.springframework.orm.hibernate4.HibernateExceptionTranslator"/>
    
    	<!-- enable the configuration of transactional behavior based on annotations -->
    	<tx:annotation-driven/>
     	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    		<property name="entityManagerFactory" ref="entityManagerFactory" />
    	</bean>
    
    	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    		<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
    		<property name="url" value="jdbc:hsqldb:mem:." />
    		<property name="username" value="sa" />
    		<property name="password" value="" />
    	</bean>
    
        <jpa:repositories base-package="edu.illinois.ncsa" transaction-manager-ref="transactionManager"/>
    </beans>
    Let me know if this is enough to help.

    Thanks,
    Rob
    Last edited by kooper; Apr 11th, 2012, 10:38 PM.

  • #2
    Not sure what contraption you are making but your static method isn't going to be transactional. A static method cannot be proxied and as such will never have a transaction applied.

    Comment


    • #3
      Even if the method is not static I still get the same error. The code posted here is a small example to understand how the transactions work and how to avoid the lazy loading exception.

      Rob

      Comment


      • #4
        Found the solution in http://forum.springsource.org/showth...nsactional-one

        Only classes that are a proxy and functions called through the proxy can define @Transactional.

        What this means (and please correct me if this is wrong) that I have to either put @Transactional on the class and use the context to get an instance of the bean, or put @Transactional on a method and call that method from outside of my proxies bean. No matter what the bean has to be a proxy (i.e. created using the context.getBean).

        In my case everything was correct except that I used new to create the class. This was done because the full application will be running in eclipse and instances of my class will be created outside of my control (i.e. by eclipse).

        Rob

        Comment

        Working...
        X