getting infinite recursion with JPA hibernate by @OneToMany and @ManyToOne

Viewed 2220

I have a problem that I can't solve, I tried it with JsonIgnore too, but it didn't work either. I have a ToDo list, and I want my tasks to output the UserID I gave to them. The problem is because every user has a Task array, the tasks are giving me an infinite loop of tasks and users.

enter image description here

that's my Code:

User:

@Entity
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

private String name;

@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private Set<Task> tasks;

Task:

@Entity
public class Task {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

private String name;

@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "user_id", nullable = false)
private User user;

then I have normal getter and setter and a toString method.

5 Answers

Use @JsonManagedReference and @JsonBackReference

User:

@Entity
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

private String name;

@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
@JsonManagedReference
private Set<Task> tasks;

Task :

@Entity
public class Task {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

private String name;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
@JsonBackReference
private User user;

In deserialization @OneToMany or @ManytoOne Relation field are also called. It's better to create response class for response rather than entity class and set your entity value in it.

public class TaskResponse {
    private int id;
    private String name;
    private UserResponse user;
    ...setter getter
}
public class UserResponse {
   private int id;
   private String name;
   ...setter getter
}

Try with the following annotations:

//--1
@OneToMany(mappedBy = "user", cascade = {CascadeType.ALL})
@JsonManagedReference
private Set`<Task>` tasks;

//--2
**@ManyToOne(cascade = CascadeType.ALL)**
@JoinColumn(name = "user_id")
@JsonBackReference
private User user;

I personally don't like mixing up responsibilities like database representation and serialization. It is totally fine to have a bidirectional graph in JPA, the only problem arises when you want to serialize this bidirectional graph into a unidirectional tree structure, that's why I would create a second representation for the unidirectional tree depending on your use-case: Either have a "task" with a shallow "user" object containing exactly those values you need in the context of a task or having a "user" with a list of shallow "task" objects containing exactly those values you need in the context of a user.

I found the solution, i had to change my getUser() method to:

    public int getUser() {
    return user.getId();
}

now I get only the userId from the task and not everything from the User, that's why I don't get a recursion anymore.

enter image description here

I hope I can help now future people that have this problem too and don't find any solution on the internet

Related