user2298581
user2298581

Reputation: 672

OneToMany and ManyToOne entities objects are linked in recursion

In my java-spring boot application I have a problem with 2 java classes with a parent-children bidirectional relationship with annotation @oneToMany and @ManyToOne.

When I try to save them on database sending a post request to the controller's endpoint, is created a recursive loop between the two objects persisted. The same problem is present when I call the @getMapping(/{fatherId}) method in the controller.

Basically java receive a Father object witch contains a set of Children which reference their Father object , which contains their children list and so on and so on..

How can I fix this issue? I've seen some similar post which suggest using Jackson library annotations, is it the absolutely necessary to add it to the pom? I would prefer having the essential minimum set of packages referenced inside my pom and Jackson is not already in the default packages written using Spring Initializer(spring boot).

Thanks for every suggestions!

The parent class is Father:

@Entity
 @Table(name="Father")
 public class Father {

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

private String name;

@OneToMany(mappedBy="father", fetch = FetchType.LAZY)
private Set<Child> children;

One Father can have many children but a child can have only one father.

The child class:

@Entity
@Table(name="Child")
public class Child {

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

private String name;

@ManyToOne
@JoinColumn(name ="ID_FATHER")
private Father father;

The endpoint in the controller is this:

@Transactional
@PostFather(path = "/newFather", consumes = "application/json", produces = "application/json")
public ResponseEntity<?> createNewFather(@Valid @RequestBody Father father, BindingResult result) {



    Set<Child> childrenSet = new HashSet<Child>();
    //ArrayList<Child> newChildren= new ArrayList<Child>();
    //newChildren.addAll(father.getChildren());
    for (Child c : father.getChildren()) {
        Child newChild = new Child();
        newChild.setId(c.getId());
        newChild.setName(c.getName());
        newChild.setFather(father);

        fatherService.saveOrUpdateChild(newChild);
        childrenSet.add(newChild);
    }
    father.setChildren(childrenSet);
    Father newFather = fatherService.saveOrUpdateFather(father);


    return new ResponseEntity<Father>(newFather, HttpStatus.CREATED);
}

@GetFather("/father/{fatherId}")
public ResponseEntity<?> getFatherById(@PathVariable int fatherId) {

    Father father = fatherService.findFatherById(fatherId);
    for (Child c : father.getChildren()) {// !!workaround to stop the loop!!
        c.setFather(null);
    }
    return ResponseEntity.ok().body(father);

}

The Problem is that when I send to

http://localhost:8080/api/myapi/newFather

the Json post request :

{
"name": "new father test 12",
"Children": [
    {
        "name": "Child test 12_1",
    },
    {
        "name": "Child test 12_2",
    },
 ]
}

I get as responce a loop:

{
   "id":197,
   "name":"father test 12",
   "children":[
      {
         "id":196,
         "name":"row test 12_1",
         "father":{
        "id":197,
        "name":"father test 12",
        "children":[
           {
              "id":196,
              "name":"row test 12_1",
              "father":{   /* ENDLESS LOOP !*/
           }
        ]
     }
  ]
  ]

Upvotes: 0

Views: 1356

Answers (1)

Just add @JsonIgnore annotation in the Father attribute in Child class

@ManyToOne
@JoinColumn(name ="ID_FATHER")
@JsonIgnore
private Father father;

Upvotes: 2

Related Questions