I am putting up a simple ER diagram to demonstrate the issue.
Each Item has a list of item details which are name/value pairs.
And we needed to serialize this object to JSON so we used Jackson. And when trying serialize we were confronted with an exception.
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ItemDetail.item, no session or session was closed
Closely looking at the generated
ItemDetail
class I found that there was a Item
defined there.
@ManyToOne(cascade={}, fetch=FetchType.LAZY)
@JoinColumn(name="item_id", unique=false, nullable=false, insertable=true, updatable=true)
public Item getItem() {
return this.item;
}
public void setItem(Item item) {
this.item = item;
}
The first (stupid) thing I tried was to change to
FetchType
from LAZY
to EAGER
. which I thought would solve the problem. However that resulted in a StackoverflowException
because the serializer kept recursing and it would never reach the end. Exception in thread "main" org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: ItemDetail["item"])
The problem here is that Hibernate provides us a way to navigate back using the foreign key relationship where in this instance to get the parent Item that belongs to each ItemDetail. But Jackson did not like it!
The solution was VERY simple.
Simply inform the serializer to ignore such parent relationships. You can inform Jackson to leave it aside using
@JsonIgnore
(See all the annotations here). @ManyToOne(cascade={}, fetch=FetchType.LAZY)
@JoinColumn(name="item_id", unique=false, nullable=false, insertable=true, updatable=true)
@JsonIgnore
public Item getItem() {
return this.item;
}
And Jackson did not try to serialize it and it worked just as expected!