org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:

Problem
I had two objects Contacts and Groups having many-to-many association.
A Contact can belong to multiple Groups and a Group can contain multiple Contacts.
My objective was to return a set of Contacts along with the Groups they were associated with.

But if the Contacts-Groups association is set to Lazy load then the above exception will be thrown.

Solution
1. FetchType can be set to EAGER and everything will work fine, the Groups will be loaded; but in a more general case, where the graph of java objects can grow very large, the use of eager fetch may cause unnecessary data to be loaded and the application will be slowed down.

2. Another solution is to explicitly load any lazy-loading the required fields actually hitting a method on those properties
   ex: contact.getEmailSet().size(). But this will result in subsequent sql firing which are required to load Groups (Child)
   Will also slow down the system.

3. Another solution is to include "fetch join" which allows associations or collections of values to be initialized along with their parent objects using a single select. This is particularly useful in the case of a collection. It effectively overrides the outer join and lazy declarations of the mapping file for associations and collections. 

Contacts Domain Object:
@Entity
@Table(name = "Contacts")
public class Contacts  implements java.io.Serializable
{
    …..
    …..
    private Set<EmailList> emailSet = new HashSet<EmailList>(0);
    ….
    ….

    @ManyToMany(targetEntity = EmailList.class, cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch= FetchType.LAZY)
    @JoinTable(name="Contacts_EmailGroup", joinColumns={@JoinColumn(name="contactsId")}, inverseJoinColumns={@JoinColumn(name="emailGroupId")})
    public Set<EmailList> getEmailSet() {
        return this.emailSet;
    }
    public void setEmailSet(Set<EmailList> emailSet) {
        this.emailSet = emailSet;
    }
}

EmailList Domain Object:
@Entity
@Table(name = "EmailGroup")
public class EmailList  implements java.io.Serializable
{
    ….
    ….
    private Set<Contacts> contacts = new HashSet<Contacts>(0);
    ….
    ….

    @ManyToMany(targetEntity = Contacts.class, cascade = { CascadeType.PERSIST, CascadeType.MERGE }, mappedBy="emailSet")
    public Set<Contacts> getContacts() {
        return this.contacts;
    }
    public void setContacts(Set<Contacts> contacts) {
        this.contacts = contacts;
    }
}

DAO layer :
private EntityManager contactsEntity;


public List<Contacts> findAllContacts()
{
   Query qry = contactsEntity.createQuery("FROM Contacts c left join fetch c.emailSet");
   return qry.getResultList();
}

 

Hope the solution will be of some use 🙂

Thanks

Sasanka

Advertisements