JSON을 쓸 수 없습니다. 무한 재귀(StackOverflowError), 중첩된 예외 스프링 부팅
후 형식을 합니다. 저장 후 데이터를 가져오려고 하면 개체 형식을 가져오려고 해도 오류가 발생합니다.getDistrict(Long id)
같은 스트라이크가 봄 환경에 매우 새로운 방법을 제안해 주십시오.
package com.gad.services;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.gad.repositories.DistrictMasterRepositories;
import com.gad.rmodels.Districtmaster;
import com.gad.rmodels.Statemaster;
@Service
public class DistricMasterServices {
@Autowired
DistrictMasterRepositories districtMasterRepositories;
@Autowired
StateMasterServices stateMasterServices;
List<Districtmaster> districtmaster;
public Iterable<Districtmaster> savenewdistrict(Long id,Districtmaster districtmaster_rec){
System.out.println(id);
Statemaster statemaster=null;
statemaster = stateMasterServices.getStateById(id);
System.out.println("savenewdistrict");
districtmaster_rec.setStatemaster(statemaster);
districtMasterRepositories.save(districtmaster_rec);
Iterable<Districtmaster>districtmaster2 = districtMasterRepositories.findAll();
return districtmaster2;
}
public Districtmaster getDistrict(Long id){
Districtmaster districtmaster = districtMasterRepositories.findOne(id);
return districtmaster;
}
}
상태의 모델 클래스:
package com.gad.rmodels;
import static javax.persistence.GenerationType.SEQUENCE;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
/**
* Statemaster generated by hbm2java
*/
@Entity
@Table(name="statemaster"
,schema="aop_gad_v1"
)
public class Statemaster implements java.io.Serializable {
private long id;
private String stateName;
private Set<Districtmaster> districtmasters = new HashSet<Districtmaster>(0);
public Statemaster() {
}
public Statemaster(long id) {
this.id = id;
}
public Statemaster(long id, String stateName, Set<Districtmaster> districtmasters) {
this.id = id;
this.stateName = stateName;
this.districtmasters = districtmasters;
}
@SequenceGenerator(name="generator_statemasterid", sequenceName="aop_gad_v1.gad_statemaster_seq")
@Id
@GeneratedValue(strategy=SEQUENCE, generator="generator_statemasterid")
@Column(name="id", unique=true, nullable=false)
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
@Column(name="state_name", length=20)
public String getStateName() {
return this.stateName;
}
public void setStateName(String stateName) {
this.stateName = stateName;
}
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="statemaster")
public Set<Districtmaster> getDistrictmasters() {
return this.districtmasters;
}
public void setDistrictmasters(Set<Districtmaster> districtmasters) {
this.districtmasters = districtmasters;
}
}
원위형 모델:
package com.gad.rmodels;
import static javax.persistence.GenerationType.SEQUENCE;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
/**
* Districtmaster generated by hbm2java
*/
@SuppressWarnings("serial")
@Entity
@Table(name="districtmaster",schema="aop_gad_v1")
public class Districtmaster implements java.io.Serializable {
private long id;
private Statemaster statemaster;
private String districtName;
private Set<GadGuestHouseMaster> gadGuestHouseMasters = new HashSet<GadGuestHouseMaster>(0);
public Districtmaster() {
}
public Districtmaster(long id) {
this.id = id;
}
public Districtmaster(long id, Statemaster statemaster, String districtName, Set<GadGuestHouseMaster> gadGuestHouseMasters) {
this.id = id;
this.statemaster = statemaster;
this.districtName = districtName;
this.gadGuestHouseMasters = gadGuestHouseMasters;
}
@SequenceGenerator(name="generator_districtmasterid", sequenceName="aop_gad_v1.gad_districtmasterid_seq")
@Id
@GeneratedValue(strategy=SEQUENCE, generator="generator_districtmasterid")
@Column(name="id", unique=true, nullable=false)
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="district_of_state")
public Statemaster getStatemaster() {
return this.statemaster;
}
public void setStatemaster(Statemaster statemaster) {
this.statemaster = statemaster;
}
@Column(name="district_name", length=20)
public String getDistrictName() {
return this.districtName;
}
public void setDistrictName(String districtName) {
this.districtName = districtName;
}
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="districtmaster")
public Set<GadGuestHouseMaster> getGadGuestHouseMasters() {
return this.gadGuestHouseMasters;
}
public void setGadGuestHouseMasters(Set<GadGuestHouseMaster> gadGuestHouseMasters) {
this.gadGuestHouseMasters = gadGuestHouseMasters;
}
}
표시되는 에러:
[{"timestamp":1512641978311, status":200, error":"OK", exception":org.springframework.http.converter.Http Message Not Writable예외","message"":JSON: 무한재귀(StackOverflowError)에 쓸 수 없습니다.네스트된 예외는 com.fasterxml.jackson.databind입니다.Json Mapping Exception:무한 재귀(StackOverflowError) (참조 체인: com.gad.rmodels 경유).Statemaster ["districtmasters\"]->org.hibernate.collection.내부의.영속적설정[0]-
Statemaster 모델에는 Statemaster 모델의 객체가 포함되어 있으며, Statemaster 모델 자체에는 Statemaster 모델의 객체가 포함되어 있기 때문에 이 문제가 발생합니다.이로 인해 무한 json 재귀가 발생합니다.
이 문제는 세 가지 방법으로 해결할 수 있습니다.
1 - DTO를 작성하고 응답에 표시할 필드만 포함합니다.
- 아는데요? - 아는데요? - 요?@JsonManagedReference
★★★★★★★★★★★★★★★★★」@JsonBackReference
석입니니다다
": " 를 합니다.@JsonManagedReference
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
@JsonManagedReference
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="statemaster")
public Set<Districtmaster> getDistrictmasters() {
return this.districtmasters;
}
, 그럼 여기에다가 더해져요.@JsonBackReference
디스트릭트 마스터 모델에 대한 주석입니다.
@JsonBackReference
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="district_of_state")
public Statemaster getStatemaster() {
return this.statemaster;
}
- 3 - 지만 를 사용할 수 .@JsonIgnore
methodgetter setter에 입니다.
@JsonIgnore
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="statemaster")
public Set<Districtmaster> getDistrictmasters() {
return this.districtmasters;
}
단, 이 접근방식은 응답에서 지역 마스터 세트를 제외합니다.
며칠째 같은 문제로 고민하고 있습니다.@JsonIgnore, @JsonManagedReference 및 @JsonBackReference 주석, 심지어 @JsonIdentity 주석도 시도했습니다.정보 주석이지만 제대로 작동하지 않았습니다.
미래의 독자들도 같은 상황에 처해 있다면, @JsonIgnore 또는 @JsonManagedReference / @JsonBackReference를 속성 자체가 아닌 속성 getter에 넣기만 하면 됩니다.그걸로 충분해
다음으로 간단한 예를 제시하겠습니다.
주문과 제품, 그리고 One To Many의 두 가지 클래스가 있다고 합시다.
주문 클래스
public class Order{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private String id_order;
private double price;
@OneToMany(mappedBy = "order")
@LazyCollection(LazyCollectionOption.FALSE)
private List<Product> products
//constructor, getters & setter
}
제품 클래스:
public class Product{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private String id_product;
private String name;
@ManyToOne
@JoinColumn(name = "id_order")
private Order order;
//consturctor, getters & setters
}
따라서 @JsonManagedReference 및 @JsonBackReference를 사용하려면 다음과 같이 getters에 추가합니다.
public class Order{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private String id_order;
private double price;
@OneToMany(mappedBy = "order")
@LazyCollection(LazyCollectionOption.FALSE)
private List<Product> products
//constructor, getters & setter
@JsonManagedReference
public List<Product> getProducts(){
return products;
}
제품 클래스:
public class Product{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private String id_product;
private String name;
@ManyToOne
@JoinColumn(name = "id_order")
private Order order;
//consturctor, getters & setters
@JsonBackReference
public Order getOrder(){
return order;
}
}
조인 테이블을 나타내는 클래스를 사용하고 있었기 때문에 @JsonBackReference와 @JsonManagedReference는 기능하지 않았습니다.또한 이 클래스가 동작하려면 링크된 클래스를 나타내는 필드 위에 @JsonBackReference를 배치해야 합니다.결과적으로 JSON을 사용하여 Join 클래스에서 레코드를 가져오면 Join 필드가 표시되지 않아 반환된 정보가 무용지물이 됩니다.
예를 들어 설명하겠지만 긴 답변은 피하고 싶습니다.@JsonIdentity아래 기사에서 설명하는 정보는 짧고 단순하지만 매우 효율적인 솔루션을 제공합니다.
그는 that는Statemaster
의 한 of Districtmaster
을 사용하다 각각의 ★★★★★★★★★★★★★★★★★.Districtmaster
가지고 있다Statemaster
json.json에 도 합니다.
@JsonIgnore
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY,
mappedBy="statemaster")
public Set<Districtmaster> getDistrictmasters() {
return this.districtmasters;
}
" " " @JsonIgnore
은요.Set<Districtmaster>
재발을 막을 수 있습니다. you붙붙 you you이다를 넣으면 돼요.@JsonIgnore
public Statemaster getStatemaster()
어느 하나.
이 문제는 양방향 매핑을 처리할 때 발생합니다.@JsonManagedReferenc
★★★★★★★★★★★★★★★★★」@JsonBackReference
D에서AO / 티티 a a a
@JsonManagedReference
정상적으로 입니다. @JsonBackReference
을 사용하다시리얼라이제이션에서는 생략됩니다.
서서 Statemaster
메이커districtmasters
a List<Districtmaster>
Set<Districtmaster>
.게터 방법을 바꾸면 됩니다.public List<Districtmaster> getDistrictmasters()
아쉽게도 이유는 설명할 수 없지만, 저는 이것이 효과가 있었습니다.
Set 대신 List를 사용합니다.나는 이렇게 문제를 해결했다.
Lombok을 사용하는 경우:
는 아마 '어느 정도'를 사용하는 것이 일 수 .Lombok
셋업할 수 있습니다.
으로 롬복족이 equals
Set
두 개체가 동일한지 여부를 판별합니다.equals
는 Lombok이라고 .equals
, equals
아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아.
하려면 둘 중 .List
Set
, 을 equals
★★★★★★★★★★★★★★★★★」hashCode
을 사용하다
또 다른 StackOverflow 질문에서 이 질문을 발견했습니다.
면면상상상상문문문문문것요요요요요요요 。를 Statemaster
는 serializer를 을 호출합니다.Districtmaster
할 수 있도록 Statemaster
해결할 수 있는 방법은 두 가지가 있습니다.
- 프록시 해제 객체
- Create DTO(Data Transfer Object) - 필요한 모든 필드를 할당하고 DTO를 반환해야 하는 엔티티의 복사본입니다.
이 문제를 해결하는 방법은 두 가지가 있습니다.
- 이 모든 걸 다 해야 돼
@Data
사용 중인 클래스/DTO를 반드시 생성해야 합니다.private static final long serialVersionUID
수업을 위해.장점: 이 방법으로 "lombok" @Data/@Getter/@Setter 주석을 사용할 수 있습니다.
- 사용 중인 모든 클래스/DTO의 모든 getter/setter에 @JsonIgnore를 추가합니다.단점: "lombok" @Data/@Getter/@Setter 주석을 사용하면 문제가 발생할 수 있습니다.
프로젝트에서 받은 오류 메시지
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion
제 경우에도 이 문제를 해결하기 위해 @JsonIgnore를 사용하고 있으며, 정상적으로 동작하고 있습니다.그리고 @JsonIgnore를 @JsonBackReference로 바꿉니다.
시나리오를 이해하려면 프로젝트, 배우자, 주소 및 직원 클래스를 확인하십시오.
주소 클래스
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;
@Getter
@Setter
@ToString
@NoArgsConstructor
@EqualsAndHashCode
@Entity
@Table(name = "address")
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String line1;
private String line2;
private String zipCode;
private String city;
private String state;
private String country;
@JsonIgnore
//@JsonBackReference
@ManyToOne
private Employee employee;
public Address(String line1, String line2, String zipCode, String city, String state, String country, Employee employee) {
this.line1 = line1;
this.line2 = line2;
this.zipCode = zipCode;
this.city = city;
this.state = state;
this.country = country;
this.employee = employee;
}
}
종업원 클래스
@Getter
@Setter
@NoArgsConstructor
@ToString
@EqualsAndHashCode
@Entity
@Table(name = "employee")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", unique = true, nullable = false)
private Integer employeeId;
private String employeeName;
private String employeeCity;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "fk_spouse")
private Spouse spouse;
@OneToMany(cascade = CascadeType.ALL)
private List<Address> addresses;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "employee_project",
joinColumns = @JoinColumn(name = "fk_employee"),
inverseJoinColumns = @JoinColumn(name = "fk_project"))
private List<Project> projects;
public Employee(String employeeName, String employeeCity, Spouse spouse, List<Address> addresses, List<Project> projects) {
this.employeeName = employeeName;
this.employeeCity = employeeCity;
this.spouse = spouse;
this.addresses = addresses;
this.projects = projects;
}
public void removeProject(Project project){
this.projects.remove(project);
project.getEmployees().remove(project);
}
public void addProject(Project project){
this.projects.add(project);
project.getEmployees().add(this);
}
}
프로젝트 클래스
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.*;
import javax.persistence.*;
import java.util.List;
@Getter
@Setter
@ToString
@EqualsAndHashCode
@NoArgsConstructor
@Entity
@Table(name = "project")
public class Project {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private String clientName;
@JsonIgnore
// @JsonBackReference
@ManyToMany(mappedBy = "projects")
private List<Employee> employees;
public Project(String name, String clientName, List<Employee> employees) {
this.name = name;
this.clientName = clientName;
this.employees = employees;
}
}
배우자 클래스
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.*;
import javax.persistence.*;
@Getter
@Setter
@NoArgsConstructor
@ToString
@EqualsAndHashCode
@Entity
@Table(name = "spouse")
public class Spouse {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String mobileNo;
private Long age;
// @JsonBackReference
@JsonIgnore
@OneToOne(mappedBy = "spouse")
private Employee employee;
public Spouse(String name, String mobileNo, Long age, Employee employee) {
this.name = name;
this.mobileNo = mobileNo;
this.age = age;
this.employee = employee;
}
}
무한 재귀(StackOverflowError)를 해결하기 위해 @JsonIgnore와 @JsonManagedReference, @JsonBackReference가 모두 사용되고 있음을 알고 있습니다.
정답.
잭슨 주석입니다.
@JsonIgnore는 무한 재귀(StackOverflowError) 문제를 해결하기 위해 생성되지 않고 직렬화 및 역직렬화 속성만 무시합니다. 무한 재귀는 피하십시오.
또한 @JsonManagedReference 및 @JsonBackReference는 필드 간의 두 가지 링크 처리를 위해 작성되었습니다.시리얼라이제이션 또는 역직렬화 프로세스에서 이러한 속성이 필요하지 않은 경우 @JsonIgnore를 사용할 수 있습니다.그렇지 않으면 @JsonManagedReference/@JsonBackReference 쌍을 사용하는 것이 좋습니다.
언급URL : https://stackoverflow.com/questions/47693110/could-not-write-json-infinite-recursion-stackoverflowerror-nested-exception