Search code examples
spring-boothibernatemany-to-many

@ManyToMany SpringBoot JSON 415 error can`t post to table or can`t get list(n>=1) because of infinite loop caused by relationship


I`ve been trying to create a @ManyToMany relationship between two entities (team&contest) but when i try to post to the contest controller api i get a error 415 saying that

Failed to evaluate Jackson deserialization for type [[simple type, class com.project.Contest.Contest]]: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot handle managed/back reference 'defaultReference': back reference type (`java.util.List<com.project.Contest.Contest>`) not compatible with managed type (com.project.Contest.Contest)

team :

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "team")
public class Team {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @JsonBackReference
    //@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class , property = "id")
    @ManyToMany(mappedBy = "teams", cascade = CascadeType.PERSIST)
    private List<Contest> contests;

    private String name;

    private int wins, losses;


}

contest :

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "contest")
public class Contest {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String name;

    @ManyToMany(cascade = CascadeType.PERSIST)
    @JsonManagedReference
    //@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class , property = "id")
    @JoinTable(
            name = "team_contest",
            inverseJoinColumns = @JoinColumn(name = "team_id"),
            joinColumns = @JoinColumn( name = "contest_id")
    )
    private List<Team> teams;

    @ManyToMany(cascade = CascadeType.PERSIST)
    @JsonManagedReference
    //@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class , property = "id")
    @JoinTable(
            name = "contest_user",
            joinColumns = @JoinColumn(name = "contest_id"),
            inverseJoinColumns = @JoinColumn( name = "user_id")
    )
    private List<User> users;


}

i found out i can use @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class , property = "id") instead of @JsonBackReference & @JsonManagedReference which helped me as it let me post to the database but then i refaced the problem that i can`t retrieve contest.teams[1] as because both objects have references to one another it creates some kind of an infinite loop as to get to the reference of the second object(contest.teams[1]) it needs to show the reference the contest.teams[0] has to the contest and soo forth. please help <3


Solution

  • This is the most famous bi-directional issue. To break up the loop while serialization, you can choose:

    1. @JsonIgnore
    2. @JsonIdentityInfo
    3. JPA Projections
    4. @EntityGraph Or simply make the relationship uni-directional