상황
TimeLine과 관계를 @OneToMany로 맺고 있는 엔티티가 아래와 같이 있다.
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Builder
@Entity(name = "time_line")
public class TimeLine {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="timeline_seq")
private Long timelineSeq;
@ManyToOne(fetch = FetchType.LAZY)
@JsonIgnore
@JoinColumn(name="user_seq",nullable = false)
private Member member;
@Column(name="title")
private String title;
@Column(name="content")
private String content;
@Column(name="regdate")
private Date regDate = new Date();
@Column(name="moddate")
private Date modDate;
@Column(name="read_count")
private Long readCount;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "timeLine")
List<TimeLineReply> timeLineReply = new ArrayList<>();
@OneToMany(fetch = FetchType.LAZY, mappedBy = "timeLine", cascade = CascadeType.PERSIST)
List<TimeLineHashTag> timeLineHashTag = new ArrayList<>();
@OneToMany(fetch = FetchType.LAZY, mappedBy = "timeLine", cascade = CascadeType.PERSIST)
List<TimeLinePhoto> timeLinePhotos = new ArrayList<>();
@OneToMany(fetch = FetchType.LAZY, mappedBy = "timeLine")
List<TimeLineLike> timeLineLikes = new ArrayList<>();
@PrePersist
public void prePersist(){
if(regDate == null) regDate = new Date();
if(readCount == null) readCount = 0L;
}
}
TimeLine과 TimeLineReply, TimeLineHashTag, TimeLinePhoto, TimeLineLike는 각각 일대다 관계를 맺고 있다.
이때, TimeLine을 delete하려고 하면 어떤일이 벌어질까?
Cannot delete or update a parent row: a foreign key constraint fails~~~
이런 식으로 에러가 찍힌다.
왜냐하면 TimeLine 자식들(댓글, 해시태그, 사진, 좋아요)에는 TimeLine의 PK가 FK로 엮여있기 때문이다.
그래서 TimeLine(부모)만 삭제하면 에러가 발생되고 삭제나 업데이트에 실패하게 된다.
그렇다면 어떻게 해야할까?
해결방법
결론적으로 말하면,
setEntity(null)을 하자!
자식이 가지고 있는 부모엔티티를 null을 해주어, 연관관계를 끊어버리면 된다.
아래 예시를 살펴보자.
service 단의 코드이다.
public Map timeLineDelete(long no) {
Map result = new HashMap();
Optional<TimeLine> opTimeLine = timeLineRepository.findById(no);
if(opTimeLine.isPresent()) {
opTimeLine.get().getTimeLinePhotos().stream().forEach(photo -> {
photo.setTimeLine(null);
});
opTimeLine.get().getTimeLineHashTag().stream().forEach(tag -> {
tag.setTimeLine(null);
});
opTimeLine.get().getTimeLineReply().stream().forEach(reply -> {
reply.setTimeLine(null);
});
timeLineRepository.delete(opTimeLine.get());
result.put("result","게시글이 삭제되었습니다.");
}else {
result.put("result","게시글 삭제 실패.");
}
return result;
}
위 코드가 정상적으로 실행이 되었다면 DB에는 아래와 같은 변화가 생긴다.
'Back > JPA' 카테고리의 다른 글
[JPA, QueryDSL] intellij QClass import static 자동완성 단축키 (0) | 2023.03.15 |
---|---|
[JPA] Spring Data JPA (0) | 2022.03.04 |
[JPA] 연관관계 매핑, @OneToMany @ManyToOne @OneToOne @ManyToMany (0) | 2021.12.15 |
[JPA] 연관관계 매핑, 연관관계 주인 (0) | 2021.12.15 |
[JPA] JPA 엔티티 매핑 (다양한 타입, 기본키 매핑) (0) | 2021.12.15 |
댓글