为什么调用GET方法时数据库会循环?
Why is the database looping when calling the GET method?
主要实体:
它使用与“animal_passport”table 的一对一关系。一切都是按照教科书做的,应该很好用。但是由于某些原因,两个 table 在调用 get 方法时相互引用。
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;
}
}
依赖实体:
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;
}
}
控制动物实体:
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);
}
}
}
调用GET方法时,需要输出动物及其护照。但是输出了一个无穷大的json。护照里面,动物是他护照上一遍又一遍的显示。
您遇到了无限递归问题。请查看@JsonManagedReference 和
@JsonBackReference 来解决这个问题。
你必须用 Jackson 注释打破循环。
一方面你可以设置 @JsonManagedReference
这将被序列化,另一方面你设置 @JsonBackReference
这将被忽略。
请在这里找到一个很好的解释:https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion
主要实体: 它使用与“animal_passport”table 的一对一关系。一切都是按照教科书做的,应该很好用。但是由于某些原因,两个 table 在调用 get 方法时相互引用。
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;
}
}
依赖实体:
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;
}
}
控制动物实体:
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);
}
}
}
调用GET方法时,需要输出动物及其护照。但是输出了一个无穷大的json。护照里面,动物是他护照上一遍又一遍的显示。
您遇到了无限递归问题。请查看@JsonManagedReference 和 @JsonBackReference 来解决这个问题。
你必须用 Jackson 注释打破循环。
一方面你可以设置 @JsonManagedReference
这将被序列化,另一方面你设置 @JsonBackReference
这将被忽略。
请在这里找到一个很好的解释:https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion