This is my District Controller, when I try to fetch data after saving I get the error, even when I try get object form getDistrict(Long id)
the same strikes ple
You are facing this issue because the Statemaster model contains the object of Districtmaster model, which itself contains the object of Statemaster model. This causes an infinite json recursion.
You can solve this issue by 3 methods.
1 - Create a DTO and include only the fields that you want to display in the response.
2 - You can use the @JsonManagedReference
and @JsonBackReference
annotations.
E.g. Add the @JsonManagedReference
annotation to the Statemaster model.
@JsonManagedReference
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="statemaster")
public Set<Districtmaster> getDistrictmasters() {
return this.districtmasters;
}
Add the @JsonBackReference
annotation to the Districtmaster model.
@JsonBackReference
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="district_of_state")
public Statemaster getStatemaster() {
return this.statemaster;
}
3 - You can use the @JsonIgnore
annotation on the getter or setter method.
@JsonIgnore
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="statemaster")
public Set<Districtmaster> getDistrictmasters() {
return this.districtmasters;
}
However, this approach will omit the set of Districtmaster from the response.
@JsonBackReference and @JsonManagedReference didn't work for me since I was using a class that represented a join table and the only way to get it to work was to put the @JsonBackReference above the fields representing the linked classes. The net effect was that if I was pulling a record from the join class using JSON, none of the join fields would show up, making the returned information useless.
I'd give examples but I like to avoid long replies. @JsonIdentityInfo explained in the article below provides a short, simple but highly efficient solution.
Bidirectional relationships and InfiniteRecursion
In the Statemaster
class make districtmasters
a List<Districtmaster>
instead of Set<Districtmaster>
and change the getter method accordingly: public List<Districtmaster> getDistrictmasters()
.
Unfortunately I can not explain why, but this worked for me.
Looks like your problem is Hibernate relations. When you try to serialize the entity Statemaster
the serializer calls serialization of the Districtmaster
set which in turn somehow reference the Statemaster
again.
There are two possible ways to solve:
I've been struggling with the same problem for days, I tried @JsonIgnore, @JsonManagedReference and @JsonBackReference annotation, and even @JsonIdentityInfo annotation and none of them have worked.
If you (the future readers ) are in the same situation, the solution is easier than you expected, simply put @JsonIgnore or @JsonManagedReference / @JsonBackReference on the attribute's getter and not on the attribute itself. And that will do.
Here's a simple example how to do so :
Say we have two classes, Order and Product, and OneToMany relation between them.
Order class
public class Order{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private String id_order;
private double price;
@OneToMany(mappedBy = "order")
@LazyCollection(LazyCollectionOption.FALSE)
private List<Product> products
//constructor, getters & setter
}
Product Class:
public class Product{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private String id_product;
private String name;
@ManyToOne
@JoinColumn(name = "id_order")
private Order order;
//consturctor, getters & setters
}
So in order to use @JsonManagedReference and @JsonBackReference, just add them to the getters as the following :
public class Order{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private String id_order;
private double price;
@OneToMany(mappedBy = "order")
@LazyCollection(LazyCollectionOption.FALSE)
private List<Product> products
//constructor, getters & setter
@JsonManagedReference
public List<Product> getProducts(){
return products;
}
Product class:
public class Product{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private String id_product;
private String name;
@ManyToOne
@JoinColumn(name = "id_order")
private Order order;
//consturctor, getters & setters
@JsonBackReference
public Order getOrder(){
return order;
}
}
That's because for Statemaster
in json the set of Districtmaster
's is put.
And each Districtmaster
has the Statemaster
in itself, so it's also put into the json. So that you get the infinite recursion
@JsonIgnore
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY,
mappedBy="statemaster")
public Set<Districtmaster> getDistrictmasters() {
return this.districtmasters;
}
Adding @JsonIgnore
annotation on Set<Districtmaster>
will prevent that recursion.
You can put the @JsonIgnore
at public Statemaster getStatemaster()
either.