Infinite loop with spring-boot in a one to many relation

21,315

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)

Share:
21,315
robert trudel
Author by

robert trudel

Updated on May 18, 2021

Comments

  • robert trudel
    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
    Safdar Akrami over 6 years
    Please do comment if you didn't get the solution yet.
  • Kartikeya Mishra
    Kartikeya Mishra about 6 years
    but this wont give me lodgerId in result from second object
  • NIKHIL CHAURASIA
    NIKHIL CHAURASIA over 3 years
    This 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
    Abd Abughazaleh about 3 years
    Can you explain more about that in example please !