| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
Tags
- 프로그래머스
- 자료구조
- nosql
- db
- 완전탐색
- jpa
- javascript
- 트러블슈팅
- 영속성 컨텍스트
- HTML
- CS
- spring
- mysql
- Docker
- CSS
- redis
- PYTHON
- websocket
- BFS
- 백준
- DFS
- Data structure
- 알고리즘
- java
- Algorithm
- It
- 데이터베이스
- 운영체제
- OS
- 트랜잭션
Archives
- Today
- Total
If at first you don't succeed, try again
[트러블슈팅] 엔티티에 @ToString 사용으로 인한 순환참조(feat. JPA) 본문
* 문제 상황
우선 Post엔티티와 PostImage 엔티티는 양방향 연관관계로 설정했다.
하나의 Post는 여러 개의 PostImage를 가질 수 있고(1 : N)
PostImage는 하나의 Post에 속해 있기 때문이었다.(N : 1)
그리고 Post 엔티티와 PostImage 엔티티에는 디버깅을 하기 위해서 @ToString 을 썼었다.
@Entity
@Table(name = "post")
@Getter
@AllArgsConstructor
@NoArgsConstructor
@EntityListeners(AuditingEntityListener.class)
@Builder
@ToString
public class Post {
...
@OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true)
@Builder.Default
private List<PostImage> postImages = new ArrayList<>();
...
}
@Entity
@Table(name = "post_image")
@Getter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Builder
@ToString
public class PostImage {
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "post_id", nullable = false)
private Post post;
...
}
그런데 서버를 실행했을 때, StackOverFlowError가 발생했다.
* 원인
원인은 양방향 연관관계에 있는 엔티티에 @ToString 사용 시 순환 참조로 인해 무한 반복이 되기 때문이었다.
순환 참조의 흐름은 이렇다.
- Post 객체를 출력하면 postImage.toString()이 호출된다.
- PostImage 객체의 toString()에서 post.toString()이 호출된다.
- post 내에 있는 Post의 toString()이 다시 호출된다.
- 무한 반복
- 메서드 호출이 중첩될수록 Stack 영역의 메모리에 계속해서 데이터가 쌓이게 되고, 결국 호출 스택이 넘치게 된다.
- StackOverflowError 발생
* 해결 방법
해결방법은 굉장히 간단한데, 엔티티에 @ToString을 되도록 붙이지 않는 것이다.
* 대체 방안
다른 해결 방법은 @ToString.Exclude를 사용하는 것이다.
@Entity
@Table(name = "post_image")
@Getter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Builder
public class PostImage {
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "post_id", nullable = false)
@ToString.Exclude
private Post post;
...
}
'개발 > 트러블슈팅' 카테고리의 다른 글
| [트러블슈팅] 커서 기반 무한 스크롤의 댓글 수, 좋아요 수를 조회하는 쿼리에서 발생했던 성능 문제(feat. N+1) (0) | 2025.06.04 |
|---|---|
| [트러블슈팅] DTO 필드 변수의 prefix 이슈 (0) | 2025.06.04 |
| [트러블슈팅] 게시물 작성에서 사진 업로드 시 발생했던 문제 (1) | 2025.06.04 |
| [트러블슈팅] Gradle 버전 문제 (0) | 2023.10.05 |