[JPA ERROR] Could not write JSON: Infinite recursion (StackOverflowError);
# ERROR:
2024-11-14 15:51:29,179 ERROR [com.cobim.cobimproj.exception.GlobalExceptionHandler] handleException: {}
org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: owError) (through reference chain: co["files"]->org.hibernate.collection.internal.PersistentBag[0]->co["card"]->co["files"]->org.hibernate.collection.internal.PersistentBag[0]->co["card"]->co["files"]->org.hibernate.collection.internal.PersistentBag[0]->co["card"]->co["files"]->org.hibernate.collection.internal.PersistentBag[0]->co["card"]->co["files"]->org.hibernate.collection.internal.PersistentBag[0]->co["card"]-
#원인 : api 호출시 해당 JPA의 테이블 열에서 데이터 불러오는게 무한 재귀가 일어나서 나타는 에러.
# 해결 :
1. @JsonIgnore : 이 어노테이션을 붙이면 json 데이터에 해당 프로퍼티는 null로 들어가게 된다. 즉, 데이터에 아예 포함이 안되게 된다.
2. @JsonManagedReference와 @JsonBackReference : 이 두개의 어노테이션이야말로 순환참조를 방어하기 위한 Annotation이다. 부모 클래스 (User entity)에 @JsonManagedReference를, 자식 클래스측(Account entity)에 @JsonBackReference 어노테이션을 추가해주면 된다.
3. DTO 사용 : 위와 같은 상황이 발생하게 된 주 원인은 '양방향 맵핑'이기도 하지만, 더 정확하게는 entity 자체를 response로 리턴한데에 있다. entity 자체를 return 하지 말고, dto 객체를 만들어 필요한 데이터만 옮겨담아 client로 리턴하면 순환참조와 관련된 문제는 애초에 방어할수 있다.
4. 맵핑 재설정 : 사람마다 다르지만 양방향 맵핑이 꼭 필요한지 다시 한번 생각해볼 필요가 있다. 만약 양쪽에서 접근 할 필요가 없다면 단방향 맵핑을 하면 자연스레 순환참조가 해결된다.
# 아래는 내가 해결한
ex)
card class & cardFile class
@Data
@Entity
@Table(name = "card")
@AllArgsConstructor
@NoArgsConstructor
public class Card {
@OneToMany(mappedBy = "card", cascade = CascadeType.ALL, orphanRemoval = true)
private List<CardFile> files = new ArrayList<>();
=> (변경)
@OneToMany(mappedBy = "card", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonManagedReference
private List<CardFile> files = new ArrayList<>();
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
public class CardFile {
@ManyToOne
private Card card;
=>(변경)
@ManyToOne
@JsonBackReference
private Card card;
# 참고 사이트
https://m.blog.naver.com/writer0713/221587351970
[JPA] 순환참조와 해결 방법 @JsonIgnore, @JsonManagedReference, @JsonBackReference
실무에서 개발을 진행하다가 희안한 현상을 맞닥뜨렸다. JPA를 사용하여 개발을 진행하면서 여러 Entit...
blog.naver.com