When trying to convert a JPA object that has a bi-directional association into JSON, I keep getting
org.codehaus.jackson.map.JsonMappingException: Infinite
I also met the same problem. I used @JsonIdentityInfo
's ObjectIdGenerators.PropertyGenerator.class
generator type.
That's my solution:
@Entity
@Table(name = "ta_trainee", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Trainee extends BusinessObject {
...
I had this problem, but I didn't want to use annotation in my entities, so I solved by creating a constructor for my class, this constructor must not have a reference back to the entities who references this entity. Let's say this scenario.
public class A{
private int id;
private String code;
private String name;
private List<B> bs;
}
public class B{
private int id;
private String code;
private String name;
private A a;
}
If you try to send to the view the class B
or A
with @ResponseBody
it may cause an infinite loop. You can write a constructor in your class and create a query with your entityManager
like this.
"select new A(id, code, name) from A"
This is the class with the constructor.
public class A{
private int id;
private String code;
private String name;
private List<B> bs;
public A(){
}
public A(int id, String code, String name){
this.id = id;
this.code = code;
this.name = name;
}
}
However, there are some constrictions about this solution, as you can see, in the constructor I did not make a reference to List bs this is because Hibernate does not allow it, at least in version 3.6.10.Final, so when I need to show both entities in a view I do the following.
public A getAById(int id); //THE A id
public List<B> getBsByAId(int idA); //the A id.
The other problem with this solution, is that if you add or remove a property you must update your constructor and all your queries.
The new annotation @JsonIgnoreProperties resolves many of the issues with the other options.
@Entity
public class Material{
...
@JsonIgnoreProperties("costMaterials")
private List<Supplier> costSuppliers = new ArrayList<>();
...
}
@Entity
public class Supplier{
...
@JsonIgnoreProperties("costSuppliers")
private List<Material> costMaterials = new ArrayList<>();
....
}
Check it out here. It works just like in the documentation:
http://springquay.blogspot.com/2016/01/new-approach-to-solve-json-recursive.html
You may use @JsonIgnore
to break the cycle (reference).
You need to import org.codehaus.jackson.annotate.JsonIgnore
(legacy versions) or com.fasterxml.jackson.annotation.JsonIgnore
(current versions).
@JsonIgnoreProperties is the answer.
Use something like this ::
@OneToMany(mappedBy = "course",fetch=FetchType.EAGER)
@JsonIgnoreProperties("course")
private Set<Student> students;
In my case it was enough to change relation from:
@OneToMany(mappedBy = "county")
private List<Town> towns;
to:
@OneToMany
private List<Town> towns;
another relation stayed as it was:
@ManyToOne
@JoinColumn(name = "county_id")
private County county;