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 two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

3 Responses to "Four solutions to the LazyInitializationException – Part 2"

  1. Me says:

    Clap clap for you mate. Nice and easy.

  2. Nice tips… Congratulations!

  3. PabloC says:

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

Leave a Reply


× 9 = thirty six



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

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

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close