Infinite Recursion with Jackson JSON and Hibernate JPA issue


When trying to convert a JPA object that has a bi-directional association into JSON, I keep getting Infinite recursion (StackOverflowError)

All I found is this thread which basically concludes with recommending to avoid bi-directional associations. Does anyone have an idea for a workaround for this spring bug?

------ EDIT 2010-07-24 16:26:22 -------


Business Object 1:

@Table(name = "ta_trainee", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
public class Trainee extends BusinessObject {

    @GeneratedValue(strategy = GenerationType.TABLE)
    @Column(name = "id", nullable = false)
    private Integer id;

    @Column(name = "name", nullable = true)
    private String name;

    @Column(name = "surname", nullable = true)
    private String surname;

    @OneToMany(mappedBy = "trainee", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @Column(nullable = true)
    private Set<BodyStat> bodyStats;

    @OneToMany(mappedBy = "trainee", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @Column(nullable = true)
    private Set<Training> trainings;

    @OneToMany(mappedBy = "trainee", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @Column(nullable = true)
    private Set<ExerciseType> exerciseTypes;

    public Trainee() {

    ... getters/setters ...

Business Object 2:

import javax.persistence.*;
import java.util.Date;

@Table(name = "ta_bodystat", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
public class BodyStat extends BusinessObject {

    @GeneratedValue(strategy = GenerationType.TABLE)
    @Column(name = "id", nullable = false)
    private Integer id;

    @Column(name = "height", nullable = true)
    private Float height;

    @Column(name = "measuretime", nullable = false)
    private Date measureTime;

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Trainee trainee;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@RequestMapping(value = "/trainees")
public class TraineesController {

    final Logger logger = LoggerFactory.getLogger(TraineesController.class);

    private Map<Long, Trainee> trainees = new ConcurrentHashMap<Long, Trainee>();

    private ITraineeDAO traineeDAO;

     * Return json repres. of all trainees
    @RequestMapping(value = "/getAllTrainees", method = RequestMethod.GET)
    public Collection getAllTrainees() {
        Collection allTrainees = this.traineeDAO.getAll();

        this.logger.debug("A total of " + allTrainees.size() + "  trainees was read from db");

        return allTrainees;

JPA-implementation of the trainee DAO:

public class TraineeDAO implements ITraineeDAO {

    private EntityManager em;

    public Trainee save(Trainee trainee) {
        return trainee;

    @Transactional(readOnly = true)
    public Collection getAll() {
        return (Collection) em.createQuery("SELECT t FROM Trainee t").getResultList();


<persistence xmlns=""
    <persistence-unit name="RDBMS" transaction-type="RESOURCE_LOCAL">
            <property name="" value="validate"/>
            <property name="hibernate.archive.autodetection" value="class"/>
            <property name="dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
            <!-- <property name="dialect" value="org.hibernate.dialect.HSQLDialect"/>         -->
3/13/2013 7:46:54 AM

Accepted Answer

You may use @JsonIgnore to break the cycle.

4/5/2019 6:46:16 PM

The new annotation @JsonIgnoreProperties resolves many of the issues with the other options.


public class Material{
   private List<Supplier> costSuppliers = new ArrayList<>();

public class Supplier{
   private List<Material> costMaterials = new ArrayList<>();

Check it out here. It works just like in the documentation:


Also, using Jackson 2.0+ you can use @JsonIdentityInfo. This worked much better for my hibernate classes than @JsonBackReference and @JsonManagedReference, which had problems for me and did not solve the issue. Just add something like:

@Table(name = "ta_trainee", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@traineeId")
public class Trainee extends BusinessObject {

@Table(name = "ta_bodystat", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@bodyStatId")
public class BodyStat extends BusinessObject {

and it should work.


Also, Jackson 1.6 has support for handling bi-directional references... which seems like what you are looking for (this blog entry also mentions the feature)

And as of July 2011, there is also "jackson-module-hibernate" which might help in some aspects of dealing with Hibernate objects, although not necessarily this particular one (which does require annotations).


Now Jackson supports avoiding cycles without ignoring the fields:

Jackson - serialization of entities with birectional relationships (avoiding cycles)


This worked perfectly fine for me. Add the annotation @JsonIgnore on the child class where you mention the reference to the parent class.

@JoinColumn(name = "ID", nullable = false, updatable = false)
private Member member;

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Email: [email protected]