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.

Related Whitepaper:

Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions

Get ready to program in a whole new way!

Functional Programming in Java will help you quickly get on top of the new, essential Java 8 language features and the functional style that will change and improve your code. This short, targeted book will help you make the paradigm shift from the old imperative way to a less error-prone, more elegant, and concise coding style that’s also a breeze to parallelize. You’ll explore the syntax and semantics of lambda expressions, method and constructor references, and functional interfaces. You’ll design and write applications better using the new standards in Java 8 and the JDK.

Get it Now!  

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

  1. Me says:

    Clap clap for you mate. Nice and easy.

  2. Nice tips… Congratulations!

Leave a Reply


+ six = 7



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
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.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books