Home » Java » Enterprise Java » Four solutions to the LazyInitializationException – Part 2

About Hebert Coelho

Senior Java Development, with 4 certifications and a published book about JSF (portuguese only). Founder of the blog uaiHebert.com visited from more than 170 different countries.

Four solutions to the LazyInitializationException – Part 2

This article continues from part 1 of the tutorial.

Load collection by Stateful EJB with PersistenceContextType.EXTENDED

This approach can be applied only to applications that works with Full JEE environments: to use a EJB with PersistenceContextType.EXTENDED.

Check the code below how the DAO would look like:

package com.ejb;

import javax.ejb.Stateful;
import javax.persistence.*;

import com.model.Person;

@Stateful
public class SystemDAOStateful {
 @PersistenceContext(unitName = 'LazyPU', type=PersistenceContextType.EXTENDED)
 private EntityManager entityManager;

 public Person findByName(String name) {
  Query query = entityManager.createQuery('select p from Person p where name = :name');
  query.setParameter('name', name);

  Person result = null;
  try {
   result = (Person) query.getSingleResult();
  } catch (NoResultException e) {
   // no result found
  }

  return result;
 }
}
public class DataMB {
 // other methods and attributes

 @EJB
 private SystemDAOStateful daoStateful;

 public Person getPersonByStatefulEJB() {
  return daoStateful.findByName('Mark M.');
 }
}
<h:dataTable var='dog' value='#{dataMB.personByStatefulEJB.lazyDogs}'>
 <h:column>
  <f:facet name='header'>
   Dog name
  </f:facet>
  #{dog.name}
 </h:column>
</h:dataTable>

Pros and Cons of this approach:

Pros

Cons

The container will control the database transaction

Works only for JEE

The model classes will not need to be edited

N+1 effect may happen

A great amount of Stateful EJBs may affect the container memory.

This approach may create the N+1 effect and the Stateful EJB has a characteristic of not being removed/destroyed while the its session is not expired or until it lost its reference.

Warning: It is not a good practice to hold a reference to an injected EJB in objects that remain in a Pool. The JSF will create a ManagedBean pool to handle better the user requests; when it is necessary the container will increase or decrease the number of ManagedBeans in the pool. In the code of this post imagine if the container create 100 instances of ManagedBeans in the pool, the server will hold 100 Stateful EJBs in memory. The solution to this problem would be a JNDI LookUp to the Stateful EJB.

Load collection by Join Query

This solution is easy to understand and to apply.

See the code below:

 public Person findByNameWithJoinFech(String name) {
  Query query = entityManager.createQuery('select p from Person p join fetch p.lazyDogs where p.name = :name');
  query.setParameter('name', name);

  Person result = null;
  try {
   result = (Person) query.getSingleResult();
  } catch (NoResultException e) {
   // no result found
  }

  return result;
 }
 public Person getPersonByQuery() {
  return systemDAO.findByNameWithJoinFech('Mark M.');
 }
 <h:dataTable var='dog' value='#{dataMB.personByQuery.lazyDogs}'>
  <h:column>
   <f:facet name='header'>
    Dog name
   </f:facet>
   #{dog.name}
  </h:column>
 </h:dataTable>

Pros and Cons of this approach:

Pros

Cons

Just one query will be fired in the database

It would be necessary one query for each accessed collection/lazy attribute

The model classes will not need to be edited

Will bring only the desired data

The N+1 effect will not happen

This approach has the disadvantage of the need of a new query to access each model class collection/lazy attribute. If we need to query only the Person dogs we would need of a specific query. Imagine that we would need to query for the Person emails, it would be necessary a different query.

This approach can be applied to JSE and JEE.

EclipseLink and lazy collection initialization

The relationships default values are:

Relationship

Fetch

@OneToOne

EAGER

@OneToMany

LAZY

@ManyToOne

EAGER

@ManyToMany

LAZY

But the JPA Spec* says that:

The EAGER strategy is a requirement on the persistence provider runtime that data must be eagerly fetched. The LAZY strategy is a hint to the persistence provider runtime that data should be fetched lazily when it is first accessed. The implementation is permitted to eagerly fetch data for which the LAZY strategy hint has been specified. In particular, lazy fetching might only be available for Basic mappings for which property-based access is used.

As you can see in the text above, the JPA implementation may ignore the hint strategy if it wants to. The EclipseLink has a behavior with JEE and other behavior to JSE. You can see each behavior here: http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_%28ELUG%29#What_You_May_Need_to_Know_About_EclipseLink_JPA_Lazy_Loading

We can find in the internet some people saying that even with a lazy collection the EclipseLink does the n+1 queries when the entity is loaded. And we can find this behavior of users with Glassfish and EJB.

Below you will see some tips to use correctly lazy load with EclipseLink:

* JSR-000220 Enterprise JavaBeans 3.0 Final Release (persistence) 9.1.18 and will repeat to the otters JPA relationships.

The end!

In my opinion the best solution is the Join Fetch Query. It is up to you to choose the best solution to your application.

Click here to download the source code of this post. If you want to run the code of this post you will need to create a database named LazyExceptionDB and the JBoss module. Attached to the source code is the Postgres module. If you want to see how to set up the datasource and the Postgres or MySQL module you can see it here: Full WebApplication JSF EJB JPA JAAS.

I hope this post might help you.

If you have any comment or doubt just post it.

See you soon.

Reference: Four solutions to the LazyInitializationException from our JCG partner Hebert Coelho at the uaiHebert blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design

and many more ....

4 comments

  1. Clap clap for you mate. Nice and easy.

  2. Excellent and very useful note!, Thanks!!!!

  3. Just a few quick notes on how to design entities and/or your code to handle the infamous LIE.

    One other way to handle LIE is to essentially wrap those areas of your code (based on testing) to catch LIE and return something else that say “this collection you’re trying to access may have data, but I don’t have it right now.” You can design a lazy loading pattern to queue this request as a Promise and pickup the results at a later time.

    Yes, the “join fetch” and “left join fetch” are your best options but you’ll have to be careful of recursive entity definitions where a parent has a children collection of the parent type with lots of relations to other entities including ManyToMany. You also have to be careful to only join with those collections that you want. You can picture an entity Person that has a collection of addresses, a collection of emails, a collection of websites, a collection of profile options, etc – you’d have to write queries that join all those attributes or risk LIE. If you have a large database, then you risk running out of memory.

    So, depending on your object graph, you can either query for the minimal pieces that you need or query for everything (might as well just do EAGER; I don’t recommend this), add LIE exception handling, keep long running persistent context open for what you need, or revert to native query.

    I invite anyone interested to share their thoughts.

    Thx
    -Rob

Leave a Reply

Your email address will not be published. Required fields are marked *

*


− three = 1

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Do you want to know how to develop your skillset and become a ...

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!
Get ready to Rock!
To download the books, please verify your email address by following the instructions found on the email we just sent you.

THANK YOU!

Close