JSF, Hibernate and one easy solution to LazyInitializationException

1. The problem

You are using Java Server Faces, probably with JPA, using Hibernate as a JPA implementation. You have some JPA entities (those classes annotated with @Entity) and at least one of them has lazy initialized attribute. Probably some collection. When retrieving object from database, everything works fine. Transactions starts, data are selected from underlying database and an object is returned. But when JSF tries to access that object's lazily initialized property,  LazyInitializationException occurs.

 

This typically happens when you retrieve an object from database and store it in some backing bean. When JSF tries to fill the view with appropriate values, then it calls the setter of that objected retrieved from database. But the transaction has already ended. That's all.

2. The solution

a) Add this one line of code into your persistence.xml.

<property name="hibernate.enable_lazy_load_no_trans" value="true"/>

That's it. Hibernate will load object's attributes without requiring transaction to be started.

Your persistance.xml can now look similar to this example code:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="mysqlPersistenceUnit" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:/jdbc/mySQL</jta-data-source>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <shared-cache-mode>NONE</shared-cache-mode>
        <properties>
            <property name="hibernate.enable_lazy_load_no_trans" value="true"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
        </properties>
    </persistence-unit>
</persistence>

b) Use JPA's reference implementation called EclipseLink instead. I've had to come over more problems with Hibernate than with EclipseLink.