How to solve the LazyInitializationException when using JPA and Hibernate
Solution 1:
Hibernate 4.1.6 finally solves this issue: https://hibernate.atlassian.net/browse/HHH-7457
You need to set the hibernate-property hibernate.enable_lazy_load_no_trans=true
Here's how to do it in Spring:
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="packagesToScan" value="com.mycompany.somepackage"/>
<property name="jpaVendorAdapter" ref="hibernateVendorAdapter"/>
<property name="jpaDialect" ref="jpaDialect"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.enable_lazy_load_no_trans">true</prop>
</props>
</property>
</bean>
Voila; Now you don't have to worry about LazyInitializationException while navigating your domain-model outside of a hibernate-session (persistence-context in "JPA-speak")
Solution 2:
There are many ways to pre-fetch properties, so they are there after session is closed:
- Call appropriate getter. After field is fetched into bean it is there after session is closed.
- You may initialize field in EJBQL query , look for
JOIN FETCH
keyword. - Enable AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS if you're on a Hibernate version that supports it.
Several problems may occur when you try these solutions:
- The getters' invocation may be optimized away by the JIT compiler (sometimes this takes a while).
- The entities you are trying to
JOIN FETCH
may be linked through multiple 'many' relationships involving List's. In this case the resulting query returns ambiguous results and Hibernate will refuse to fetch your data in a single query. - There is already one interesting bug related to AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS. And there will be more because as the hibernate guys say: Note: this may happen outside of the transaction and is not safe. Use with caution. You're on your own mostly.
The best way to go is to try a JOIN FETCH
first. If that doesn't work try the getter approach. If that gets messed up at runtime by the JIT compiler, assign the result to a public static volatile Object
.
Or stop using Hibernate...