Home > OS >  How to use JsonIgnore in Spring Boot to stop infinite loop?
How to use JsonIgnore in Spring Boot to stop infinite loop?

Time:10-01

I have a many to many relationship in my project between User and a Product. A User can have many products and a Product can be owned by many Users.

User.java

    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinTable( name = "user_product",
                joinColumns = @JoinColumn(name = "user_id"),
                inverseJoinColumns = @JoinColumn(name = "product_id"))
    private List<Product> listOfProductsForUser;

Product.java

    @JsonIgnore
    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "listOfProductsForUser")
    private List<User> listOfUsersForProduct;

In my controller, I have a path that gets me all the users and the nested products associated with the user like this.

[
    {
        "userId": 1,
        "userName": "Fido",
        "age": 3,
        "listOfProductsForUser": [
            {
                "productId": 1,
                "productName": "tooth brush",
            },
            {
                "productId": 2,
                "productName": "potatoes",
            },
            {
                "productId": 3,
                "productName": "carrot",
            }
        ]
    },
    {
        "userId": 2,
        "userName": "David",
        "age": 12,
        "listOfProductsForUser": [
            {
                "productId": 6,
                "productName": "oranges",
            },
            {
                "productId": 7,
                "productName": "tomatoes",
            },
            {
                "productId": 6,
                "productName": "buns",
            }
        ]
    }
]

This is fine but I now want to get all products which should have nested users (to get all products and see which users are using them). While attempting to do this I run into a recursive problem and I have used JsonIgnore on the product.java's listOfProductsForUser variable as shown above to stop the recursion. How can I accomplish this?

CodePudding user response:

There are couple of ways to deal with this bi-directional relationship issue. I think @JsonIdentityInfo is the best way in your case.

What you need to do is change your User and Product class as follows.

//other annotations
@JsonIdentityInfo(
  generator = ObjectIdGenerators.PropertyGenerator.class, 
  property = "userId")
public class User {
    // your code
}
//other annotations
@JsonIdentityInfo(
  generator = ObjectIdGenerators.PropertyGenerator.class, 
  property = "productId")
public class Product {
    // your code
}

Note: For more info here

CodePudding user response:

Try the following:

@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable( name = "user_product",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "product_id"))
@JsonManagedReference
private List<Product> listOfProductsForUser;
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "listOfProductsForUser")
@JsonBackReference
private List<User> listOfUsersForProduct;

These two annotations (@JsonManagedReference and @JsonBackReference) avoid infinite recursion.

  • Related