Issue
The main entity: it uses a one-to-one relationship to the "animal_passport" table. Everything is done according to the textbook and should work well. But for some reason, both tables refer to each other when calling the get method.
package com.testapp.model;
import javax.persistence.*;
@Entity
@Table(name = "animal")
public class Animal {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "animal_id", nullable = false, updatable = false)
private long id;
@Column(name = "animal_value")
private String animal_value;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "pass_id")
private PassportAnimal passportAnimal;
public Animal(String animal_value, PassportAnimal passportAnimal) {
this.animal_value = animal_value;
this.passportAnimal = passportAnimal;
}
public Animal() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getAnimal_value() {
return animal_value;
}
public void setAnimal_value(String animal_value) {
this.animal_value = animal_value;
}
public PassportAnimal getPassportAnimal() {
return passportAnimal;
}
public void setPassportAnimal(PassportAnimal passportAnimal) {
this.passportAnimal = passportAnimal;
}
}
Dependent entity:
package com.testapp.model;
import javax.persistence.*;
@Entity
@Table(name = "pass_anim")
public class PassportAnimal {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "pass_id", nullable = false,updatable = false)
private long id;
@Column(name = "value_pass")
private String value;
@OneToOne(mappedBy = "passportAnimal")
private Animal animal;
public PassportAnimal(String value, Animal animal) {
this.value = value;
this.animal = animal;
}
public PassportAnimal() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Animal getAnimal() {
return animal;
}
public void setAnimal(Animal animal) {
this.animal = animal;
}
}
Controller the animal entity:
package com.testapp.controller;
import com.testapp.model.Animal;
import com.testapp.repository.AnimalRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@CrossOrigin(origins = "http://localhost:8080")
@RestController
@RequestMapping(path = "/api")
public class AnimalController {
@Autowired
AnimalRepository animalRepository;
@GetMapping("/animal")
public ResponseEntity<List<Animal>> getAllAnimal(@RequestParam(required = false) String value)
{
try {
List<Animal> animals = new ArrayList<>();
if (value == null) {
animalRepository.findAll().forEach(animals::add);
}
if (animals.isEmpty()) {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<>(animals, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@GetMapping("/animal/{id}")
public ResponseEntity<Animal> getAnimalById(@PathVariable("id") long id) {
Optional<Animal> animalOptional = animalRepository.findById(id);
if (animalOptional.isPresent()) {
return new ResponseEntity<>(animalOptional.get(), HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
@PostMapping("/animal")
public ResponseEntity<Animal> createAnimal(@RequestBody Animal animal) {
try {
Animal _animal = animalRepository.save(new
Animal(animal.getAnimal_value(),animal.getPassportAnimal()));
return new ResponseEntity<>(_animal, HttpStatus.CREATED);
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@PutMapping("/animal/{id}")
public ResponseEntity<Animal> updateAnimal(@PathVariable("id") long id, @RequestBody Animal
animal) {
try {
Optional<Animal> animalOptional = animalRepository.findById(id);
if (animalOptional.isPresent()) {
Animal _animal = animalOptional.get();
_animal.setAnimal_value(animal.getAnimal_value());
_animal.setPassportAnimal(animal.getPassportAnimal());
return new ResponseEntity<>(animalRepository.save(_animal), HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@DeleteMapping("/animal/{id}")
public ResponseEntity<HttpStatus> deleteAnimal(@PathVariable("id") long id) {
try {
animalRepository.deleteById(id);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@DeleteMapping("/animal")
public ResponseEntity<HttpStatus> deleteAllAnimals() {
try {
animalRepository.deleteAll();
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
When calling the GET method, the animal and its passport should be output. But an infinite json is output. Inside the passport, the animal is displayed again and again his passport.
Solution
You have to break the loop with Jackson annotations.
One one side you can set @JsonManagedReference
and this will be serialized and on the other you set @JsonBackReference
and this one will be ignored.
Please find a good explanation here: https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion
Answered By - Simon Martinelli
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.