Suggested Pages

Sunday, June 10, 2012

JPA/Hibernate:LazyInitializationException

This is one of the commonest exception that occurs in Hibernate or JPA. When you ask for a collection to an entity after the hibernate session has closed or after the object has been detached from the session, this exception may occur. As you know, you can declare an association between two entities: EAGER or LAZY. If you use LAZY when an object is retrieved from the DB, it's not initialized with the association marked as LAZY. The LAZY initialization avoids to perform a JOIN between the two entities, so only when you navigate an association marked LAZY inside a session, you hit the database for retrieving data. Suppose these are your entities:
Contact.java
 .....

@Entity
public class Contact {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int id;

 @Column
 private String number;

 @Column
 private String type;

 @ManyToOne
 private Person person;


 @Override
 public String toString() {
  return "Contact [id=" + id + ", number=" + number + ", type=" + type
    + ", person=" + person + "]";
 }


 public int getId() {
  return id;
 }


 public void setId(int id) {
  this.id = id;
 }


 public String getNumber() {
  return number;
 }


 public void setNumber(String number) {
  this.number = number;
 }


 public String getType() {
  return type;
 }


 public void setType(String type) {
  this.type = type;
 }


 public Person getPerson() {
  return person;
 }


 public void setPerson(Person person) {
  this.person = person;
 }

}


Person.java
  .....

@Entity
public class Person {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int id;
 
 @Column
 private String name;
 
 @Column
 private String surname;
 
 @OneToMany(mappedBy="person",fetch=FetchType.LAZY)
 private List<Contact> contacts;

 
 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getSurname() {
  return surname;
 }

 public void setSurname(String surname) {
  this.surname = surname;
 }

 public List<Contact> getContacts() {
  return contacts;
 }

 public void setContacts(List<Contact> contacts) {
  this.contacts = contacts;
 }

 @Override
 public String toString() {
  return "Person [id=" + id + ", name=" + name + ", surname=" + surname+"]";
 }
}



Person entity has a LAZY association with Contact, so when you invoke find method of EntityManager as:
Person person=entityManager.find(Person.class, personID);
an entity is retrieved from the database but its collection of contacts is not initialized.
Suppose now you want to access on contacts inside the presentation layer.
contacts.jsp

 <c:forEach var="contact" items="${person.contacts}">
        <tr>
          <td>${contact.number}</td>
          <td>${contact.type}</td>
         <td>
          <table>
           <tbody>
             ...
            <tr>
             <td><a href="${updateContact}">update</a></td>
            </tr>
            <tr>
             <td><a href="${deleteContact}">delete</a></td>
            </tr>
           </tbody>

          </table>
         </td>
        </tr>
       </c:forEach>
As you can see, in this JSP you are asking all contacts of a certain person. But person entity is detached at this level, so an exception will occur: LazyInitializationException. To fetch data on an association marked LAZY, the entity must be inside the session

No comments :

Post a Comment

Suggested Pages