Infinite loop with spring-boot in a one to many relation
Solution 1
Solution:
Use
@JsonManagedReference
annotation for the first objects instantiated
@JsonBackReference
annotation for the second objects instantiated
First:
@JsonManagedReference
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "lodger")
private List<Reference> referenceList;
Second:
@JsonBackReference
@ManyToOne
@JoinColumn(name = "lodgerId")
private Lodger lodger;
Solution 2
If you primary keys in both tables are same name for example : id.
Add this
@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "id")
public class User {
...
}
And to Reference class.
@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "id")
public class Reference {
...
}
Solution 3
It happens when you have a cycle in return object and spring tries to serialize it to other type.
Try to create DTO or Value Object (simple POJO) without cycles from returned model and then return it.
Solution 4
The only thing that you need is, in your class in which you have the annotation @ManyToOne
, implement the next annotation with the attributes that you want to skip in the value section
@JsonIgnoreProperties(value = {"yourAttribute", "handler", "hibernateLazyInitializer"}, allowSetters = true)
I put an example for your code ->
@ManyToOne(fetch = FetchType.LAZY)
@JsonIgnoreProperties(value = {"referenceList", "handler","hibernateLazyInitializer"}, allowSetters = true)
@JoinColumn(name = "lodgerId")
private Lodger lodger;
All the attributes that you put in the value section on the @JsonIgnoreProperties
are ignored, with this you can resolve the infinite loop and use it for other developments with the same format in the future.
Solution 5
Do not return entity with circular dependencies via REST webservice - create new DTO class, map entities fetched from database and return it in webservice.
More info here: http://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application
Of course if you want you may use another mapping library, my personal favourite is Orika (http://orika-mapper.github.io/orika-docs/intro.html)
robert trudel
Updated on May 18, 2021Comments
-
robert trudel almost 3 years
In a rest application, I use spring boot with jpa.
I have a class Lodger
who have
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "lodger") private List<Reference> referenceList;
In my class Reference, i have
@ManyToOne @JoinColumn(name = "lodgerId") private Lodger lodger;
when i call this method
@RequestMapping(value = "/lodgers/{lodgerId}", method = RequestMethod.GET) public Lodger getLogderById(@PathVariable("lodgerId") long lodgerId) { return lodgerService.getLodger(lodgerId); }
I get this error
org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: Infinite recursion (StackOverflowError) (through reference chain: server.bean.Lodger["referenceList"]->org.hibernate.collection.internal.PersistentBag[0]->server.bean.Reference["lodger"]->server.bean.Lodger["referenceList"]->org.hibernate.collection.internal.PersistentBag[0]->server.bean.Reference["lodger"]->server.bean.Lodger["referenceList"]...
-
Safdar Akrami over 6 yearsPlease do comment if you didn't get the solution yet.
-
Kartikeya Mishra about 6 yearsbut this wont give me lodgerId in result from second object
-
NIKHIL CHAURASIA over 3 yearsThis solution solves the primary problem but gives birth to another problem, i.e., now we are not getting the second referenced object at all.
-
Abd Abughazaleh about 3 yearsCan you explain more about that in example please !