Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to solve the LazyInitializationException when using JPA and Hibernate

People also ask

What is the LazyInitializationException?

Class LazyInitializationExceptionIndicates an attempt to access not-yet-fetched data outside of a session context. For example, when an uninitialized proxy or collection is accessed after the session was closed.

How will load a lazily loaded items in hibernate to avoid lazy load exception?

Just make the lazy=false and hibernate will load the child when parent is loaded from the database. In the above configuration. If lazy="false" : - when you load the Employee object that time child object Address is also loaded and set to setAddresss() method. If you call employee.


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")


There are many ways to pre-fetch properties, so they are there after session is closed:

  1. Call appropriate getter. After field is fetched into bean it is there after session is closed.
  2. You may initialize field in EJBQL query , look for JOIN FETCH keyword.
  3. 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:

  1. The getters' invocation may be optimized away by the JIT compiler (sometimes this takes a while).
  2. 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.
  3. 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...


Note that you shouldn't use hibernate.enable_lazy_load_no_trans pre Hibernate 4.1.7, as it leaks connections. See https://hibernate.onjira.com/browse/HHH-7524


LazyInitializationException means that you are calling the collection after the hibernate session has closed, or after the object has been detached from the session.

You need to either re-attach the object to hibernate session, change the place where you are calling the collection, or move the boundary of where the session gets closed to a higher layer.


The best way to solve the LazyInitializationException is to use the JOIN FETCH directive in your entity queries.

FetchType.EAGER loading is bad for performance. Also, there are anti-patterns such as:

  • Open Session in View
  • hibernate.enable_lazy_load_no_trans

Which you should never use since they either require the database connection to be open for the UI rendering (Open Session in View), or a database connection is needed for every lazy association that is fetched outside of the initial Persistence Context (hibernate.enable_lazy_load_no_trans).

Sometimes, you don't even need entities, and a DTO projection is even better. You should fetch entities only when you need to modify them. For read-only transactions, DTO projections are better.


OpenSessionInView is one pattern to deal with this problem. Some info here:

http://www.hibernate.org/43.html

You'll want to be cautious when implementing this pattern and understand the implications. Each time you navigate a lazy association in the view it will fire off another SQL query to load the data. If your use cases are such that the number and size of these SQL queries is small then this may not matter. Make sure that at a minimum you adjust your logging settings so you can see what kind of queries Hibernate is "magically" executing in the background for you to load the data.

Also consider the kind of application you are writing. If you're not dealing with remoting (no web services, no AJAX-based web client) then OSIV may work very nicely. However, if a remoting serializer starts to walk the entire object graph, it will likely trigger a ridiculous number of SQL queries and cripple your DB and app server.


When you are using collection and you want to initialize it with lazy loading then use that collection before session close. If session is close after that if you want to use then you get lazyinitializeException because lazy is try by default.