쌓고 쌓다
테스트 코드에서 DELETE 쿼리할때 a foreign key constraint fails 발생 본문
댓글과 댓글 좋아요가 1:N으로 관계를 맺고 있는 상태이다.
즉, 댓글 좋아요에서 댓글PK를 외래키로 갖고 있다.
Comment
@Entity
@Data
public class Comment {
...
@OneToMany(mappedBy = "comment", cascade = CascadeType.REMOVE)
private List<CommentLike> commentLikes = new ArrayList<>();
}
CommentLike
@Entity
@Data
public class CommentLike {
...
@ManyToOne
@JoinColumn(name = "comment_id")
private Comment comment;
}
실행한 테스트 코드는 다음과 같다.
@Test
@DisplayName("댓글 삭제")
void deleteComment() throws PermissionException {
...
commentService.deleteComment(comment.getId(), member.getId());
em.flush();
}
commentService의 deleteComment 메서드 로직은 다음과 같다.
public void deleteComment(Long commentId, Long memberId) throws PermissionException {
Comment comment = commentRepository.findById(commentId)
.orElseThrow(() -> new NoSuchElementException());
Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new NoSuchElementException())
commentRepository.delete(comment);
}
간단히 설명하자면 Comment와 Member 엔티티를 찾아 제거하는 코드이다.
실제 테스트 코드를 동작하기전 @BeforeEach로 댓글과 댓글 좋아요는 INSERT 쿼리가 나가서
테스트 데이터는 DB에 존재하는 상태이다.
그러나 테스트 코드를 실행하여 commentSerivce.deleteComment를 통해 댓글 DELETE 쿼리를 실행하면
외래키 제약에 걸리는 에러가 발생한다.
왜 Comment의 CascadeType.REMOVE를 주었음에도 불구하고
CommentLike가 삭제되지 않고 외래 키 제약에 걸리는 것일까?
한번 deleteComment 메서드 내에 Comment의 CommentLike 개수를 출력해보았다.
이상하게 CommentLike의 개수가 0개로 나온다. 분명 DB에 들어갔음에도 불구하고.
em.clear()를 실행해서 영속성 컨텍스트를 비우고 한번 테스트 코드를 실행해보자.
댓글에 달린 좋아요 개수가 정상적으로 1개로 나오며
CommentLike를 먼저 삭제하고 Comment를 삭제하는 쿼리가 정상적으로 나가는 것을 볼 수 있다.
문제의 원인은 다음과 같았다.
commentRepository의 findById 메서드를 통해 댓글을 조회했지만
이전에 @BeforeEach를 통해 영속성 시킨 Comment가(CommentLike를 갖고있지 않는 상태)
1차 캐시에 남아 있어 DB를 통해 조회하지 않고 캐시에 있던 Comment를 반환하면서
Comment에 CommentLike가 담겨 있지 않았던 것이다.
그래서 Comment만 DELETE하려고하니 CommentLike에 Comment의 PK로 외래키가 잡혀있어 예외가 발생할 것이였다.
'프로그래밍 > JPA' 카테고리의 다른 글
JPA 복합 키 사용하기 / QueryDSL N:M 관계 조회 (0) | 2024.08.31 |
---|---|
테스트 코드에서 영속성 컨텍스트를 주의하자! (0) | 2024.08.16 |
flush와 clear의 차이 (테스트 코드에서 SELECT가 안나가는 이유) (0) | 2024.03.08 |
Entity의 List 필드(컬렉션)는 초기화 해주자 (0) | 2024.03.08 |
JPA(hibernate) INSERT, UPDATE, DELETE 순서 주의사항 (1) | 2024.02.24 |