[SPRING] JSON을 작성할 수 없습니다 : 무한 재귀 (StackOverflowError); 중첩 예외 봄 부팅
SPRINGJSON을 작성할 수 없습니다 : 무한 재귀 (StackOverflowError); 중첩 예외 봄 부팅
이것은 지구 관리자입니다. 저장 후 데이터를 가져 오려고 할 때 오류가 발생합니다. 객체 양식 getDistrict (긴 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;
}
}
내가 얻은 오류
해결법
-
==============================
1.Statemaster 모델에는 Statemaster 모델의 개체가 포함 된 Districtmaster 모델의 개체가 포함되어 있기 때문에이 문제에 직면 해 있습니다. 이로 인해 무한한 json 재귀가 발생합니다.
Statemaster 모델에는 Statemaster 모델의 개체가 포함 된 Districtmaster 모델의 개체가 포함되어 있기 때문에이 문제에 직면 해 있습니다. 이로 인해 무한한 json 재귀가 발생합니다.
이 문제는 3 가지 방법으로 해결할 수 있습니다.
1 - DTO를 만들고 응답에 표시하려는 필드 만 포함하십시오.
2 - @JsonManagedReference 및 @JsonBackReference 주석을 사용할 수 있습니다.
예 : @JsonManagedReference 주석을 Statemaster 모델에 추가하십시오.
@JsonManagedReference @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="statemaster") public Set<Districtmaster> getDistrictmasters() { return this.districtmasters; }
@JsonBackReference 주석을 Districtmaster 모델에 추가하십시오.
@JsonBackReference @ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="district_of_state") public Statemaster getStatemaster() { return this.statemaster; }
3 - getter 또는 setter 메서드에서 @JsonIgnore 주석을 사용할 수 있습니다.
@JsonIgnore @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="statemaster") public Set<Districtmaster> getDistrictmasters() { return this.districtmasters; }
그러나이 접근법은 Districtmaster를 응답에서 제외합니다.
-
==============================
2.그것은 json의 Statemaster에게 Districtmaster 세트가 있기 때문입니다. 그리고 각 각의 Districtmaster는 Statemaster를 자체적으로 가지고 있으므로 json에도 넣습니다. 그래서 당신은 무한 재귀를 얻습니다.
그것은 json의 Statemaster에게 Districtmaster 세트가 있기 때문입니다. 그리고 각 각의 Districtmaster는 Statemaster를 자체적으로 가지고 있으므로 json에도 넣습니다. 그래서 당신은 무한 재귀를 얻습니다.
@JsonIgnore @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="statemaster") public Set<Districtmaster> getDistrictmasters() { return this.districtmasters; }
Set
에 @JsonIgnore 주석을 추가하면 해당 재귀가 방지됩니다. 공용 Statemaster getStatemaster ()에 @JsonIgnore를 둘 수 있습니다. -
==============================
3.나는 며칠 동안 같은 문제를 겪어 왔지만, @JsonIgnore, @JsonManagedReference 및 @JsonBackReference 주석을 시도하고 심지어 @JsonIdentityInfo 주석을 사용했으며 그 중 아무 것도 작동하지 않았습니다.
나는 며칠 동안 같은 문제를 겪어 왔지만, @JsonIgnore, @JsonManagedReference 및 @JsonBackReference 주석을 시도하고 심지어 @JsonIdentityInfo 주석을 사용했으며 그 중 아무 것도 작동하지 않았습니다.
독자 (미래의 독자)가 같은 상황에 있다면 솔루션은 예상보다 쉽습니다. @JsonIgnore 또는 @JsonManagedReference / @JsonBackReference를 속성의 getter에 넣고 속성 자체에는 넣지 마십시오. 그리고 그렇게 될 것입니다.
다음은이를 수행하는 간단한 예입니다.
Order와 Product, 그리고 OneToMany 관계라는 두 개의 클래스가 있다고 가정 해보십시오.
주문 클래스
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; } }
-
==============================
4.문제가 최대 절전 모드 인 것 같습니다. 엔티티 Statemaster를 serialize하려고하면 serializer가 Districtmaster 세트의 serialization을 호출합니다. 차례 차례로 Statemaster를 다시 참조하십시오.
문제가 최대 절전 모드 인 것 같습니다. 엔티티 Statemaster를 serialize하려고하면 serializer가 Districtmaster 세트의 serialization을 호출합니다. 차례 차례로 Statemaster를 다시 참조하십시오.
해결할 수있는 두 가지 방법이 있습니다. 1. unproxy 객체
-
==============================
5.이 문제는 양방향 매핑을 처리 할 때 발생합니다. DAO / Entity 클래스에서 @JsonManagedReferenc 및 @JsonBackReference 사용
이 문제는 양방향 매핑을 처리 할 때 발생합니다. DAO / Entity 클래스에서 @JsonManagedReferenc 및 @JsonBackReference 사용
@JsonManagedReference는 참조의 앞으로의 부분입니다 - 정상적으로 직렬화됩니다. @JsonBackReference는 참조의 뒷부분입니다. 직렬화에서 생략됩니다.
(자세히보기)
from https://stackoverflow.com/questions/47693110/could-not-write-json-infinite-recursion-stackoverflowerror-nested-exception by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Java Spring 다중 ApplicationContext (0) | 2019.06.30 |
---|---|
[SPRING] Spring은 프로덕션 용으로 하나의 application.properties를 사용하고 디버그 용으로 하나의 application.properties를 사용 (0) | 2019.06.27 |
[SPRING] @ TransactionalEvents 및 @Rollback 테스트 (0) | 2019.06.27 |
[SPRING] spring rest 템플릿을 사용하여 서비스에 HTTP 헤더 (JWT Token) 전파 (0) | 2019.06.26 |
[SPRING] Autowired는 Custom Constraint validator에서 Null 값을줍니다. (0) | 2019.06.26 |