DomiRo
DomiRo

Reputation: 176

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

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.

Upvotes: 3

Views: 7882

Answers (5)

Dumidu Udayanga
Dumidu Udayanga

Reputation: 914

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;

Upvotes: 7

Smutje
Smutje

Reputation: 18143

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.

Upvotes: 0

DomiRo
DomiRo

Reputation: 176

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

Upvotes: -2

Sahadan
Sahadan

Reputation: 1

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;

Upvotes: 0

Eklavya
Eklavya

Reputation: 18430

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
}

Upvotes: 1

Related Questions