@Data
@NoArgsConstructor
@Entity
public class Post extends BaseTimeEntity {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "POST_ID")
private Long id;
@Column
private String title;
@Column
private String summary;
@Column
private String broadcastId;
@Column(columnDefinition = "TEXT")
private String content;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "MEMBER_ID")
private Member member;
@OneToMany(mappedBy = "post", cascade = CascadeType.REMOVE, orphanRemoval = true) //Post에서만 youtube 참조
private List<Youtube> youtubes = new ArrayList<>();
@OneToMany(mappedBy = "post", cascade = CascadeType.REMOVE) //Member에서도 참조
private List<Good> goods = new ArrayList<>();
@OneToMany(mappedBy = "post", cascade = CascadeType.REMOVE, orphanRemoval = true) //Post에서만 Report 참조
private List<Report> reports = new ArrayList<>();
public Post(String title, String summary, String broadcastId, String content, Member member) {
this.title = title;
this.summary = summary;
this.broadcastId = broadcastId;
this.content = content;
this.member = member;
}
@Builder
public Post(String title, String summary, String broadcastId, String content, Member member, List<Youtube> youtubes, List<Good> goods) {
this.title = title;
this.summary = summary;
this.broadcastId = broadcastId;
this.content = content;
this.member = member;
this.youtubes = youtubes;
this.goods = goods;
}
public void update(String title, String summary, String content, List<Youtube> youtubes) {
this.title = title;
this.summary = summary;
this.content = content;
this.youtubes = youtubes;
}
//연관관계 메서드
public void addYoutube(Youtube youtube) {
this.youtubes.add(youtube);
}
public void addGood(Good good) {
this.goods.add(good);
}
public void addReport(Report report) {
this.reports.add(report);
}
}
게시글 수정 기능을 구현하던 중 에러가 발생하였다.
Hibernate에서 자식 객체를 삭제하거나 부모 객체와 연관성을 끊었지만, 변경 내용을 아직 저장하지 않은 경우 발생한다.
기존
/** 게시글 수정 */
@Transactional
public Long update(Long postId, PostUpdateRequestDto updateRequestDto) {
Post findPost = postRepository.findById(postId).orElseThrow(() -> new IllegalArgumentException("해당 글이 없습니다. id=" + postId));
List<Youtube> youtubes = youtubeRepository.findByPost(findPost);
for (Youtube youtube : youtubes) {
youtubeRepository.delete(youtube);
}
if (updateRequestDto.getReference().size() > 0) {
ArrayList<String> list = updateRequestDto.getReference();
for (int i = 0; i < list.size(); i++) {
youtubeRepository.save(updateRequestDto.toEntity(findPost, list.get(i)));
}
youtubes = youtubeRepository.findByPost(findPost);
} else {
youtubes = null;
}
findPost.update(updateRequestDto.getTitle(), updateRequestDto.getSummary(), updateRequestDto.getContent(), youtubes);
return postId;
}
변경
/** 게시글 수정 */
public Long update(Long postId, PostUpdateRequestDto updateRequestDto) {
Post findPost = postRepository.findById(postId).orElseThrow(() -> new IllegalArgumentException("해당 글이 없습니다. id=" + postId));
List<Youtube> youtubes = youtubeRepository.findByPost(findPost);
findPost.getYoutubes().clear();
List<Youtube> youtubeList = new ArrayList<>();
if (updateRequestDto.getReference().size() > 0) { //유튜브 링크가 있는 경우
ArrayList<String> list = updateRequestDto.getReference();
//Post 엔티티의 유튜브 컬렉션에 유튜브 엔티티 추가
for (int i = 0; i < list.size(); i++) {
Youtube saveYoutube = youtubeRepository.save(updateRequestDto.toEntity(findPost, list.get(i)));
youtubeList.add(saveYoutube);
}
findPost.update(updateRequestDto.getTitle(), updateRequestDto.getSummary(), updateRequestDto.getContent(), youtubeList);
} else {
findPost.update(updateRequestDto.getTitle(), updateRequestDto.getSummary(), updateRequestDto.getContent());
}
return postId;
}
코드를 위처럼 수정하였지만, 여전히 같은 문제가 발생했다.
컬렉션을 clear()로 비우면 연관관계가 끊어지고 컬렉션에 새로운 객체가 들어온 후 플러시가 되면 원래 들어있던 객체는 관계가 끊어졌기 때문에 db에서도 삭제되고 변경된 내용은 저장이 될 줄 알았다.
컬렉션을 비웠지만 플러시를 하지 않은 상태로 내용이 변경되었기 때문에 고아 객체 제거는 적용 되지 않는 것 같다.
이 경우 고아 객체 제거 기능 대신 컬렉션을 비우고 직접 db에서 delete를 해줘야 할 것 같다.
최종 변경
/** 게시글 수정 */
public Long update(Long postId, PostUpdateRequestDto updateRequestDto) {
Post findPost = postRepository.findById(postId).orElseThrow(() -> new IllegalArgumentException("해당 글이 없습니다. id=" + postId));
List<Youtube> youtubes = youtubeRepository.findByPost(findPost);
findPost.getYoutubes().clear();
for (Youtube youtube : youtubes) {
youtubeRepository.delete(youtube);
}
if (updateRequestDto.getReference().size() > 0) {
ArrayList<String> list = updateRequestDto.getReference();
//Post 엔티티의 유튜브 컬렉션에 유튜브 엔티티 추가
for (int i = 0; i < list.size(); i++) {
Youtube saveYoutube = youtubeRepository.save(updateRequestDto.toEntity(findPost, list.get(i)));
findPost.addYoutube(saveYoutube);
}
}
findPost.update(updateRequestDto.getTitle(), updateRequestDto.getSummary(), updateRequestDto.getContent());
return postId;
}
'Error' 카테고리의 다른 글
@Data
@NoArgsConstructor
@Entity
public class Post extends BaseTimeEntity {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "POST_ID")
private Long id;
@Column
private String title;
@Column
private String summary;
@Column
private String broadcastId;
@Column(columnDefinition = "TEXT")
private String content;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "MEMBER_ID")
private Member member;
@OneToMany(mappedBy = "post", cascade = CascadeType.REMOVE, orphanRemoval = true) //Post에서만 youtube 참조
private List<Youtube> youtubes = new ArrayList<>();
@OneToMany(mappedBy = "post", cascade = CascadeType.REMOVE) //Member에서도 참조
private List<Good> goods = new ArrayList<>();
@OneToMany(mappedBy = "post", cascade = CascadeType.REMOVE, orphanRemoval = true) //Post에서만 Report 참조
private List<Report> reports = new ArrayList<>();
public Post(String title, String summary, String broadcastId, String content, Member member) {
this.title = title;
this.summary = summary;
this.broadcastId = broadcastId;
this.content = content;
this.member = member;
}
@Builder
public Post(String title, String summary, String broadcastId, String content, Member member, List<Youtube> youtubes, List<Good> goods) {
this.title = title;
this.summary = summary;
this.broadcastId = broadcastId;
this.content = content;
this.member = member;
this.youtubes = youtubes;
this.goods = goods;
}
public void update(String title, String summary, String content, List<Youtube> youtubes) {
this.title = title;
this.summary = summary;
this.content = content;
this.youtubes = youtubes;
}
//연관관계 메서드
public void addYoutube(Youtube youtube) {
this.youtubes.add(youtube);
}
public void addGood(Good good) {
this.goods.add(good);
}
public void addReport(Report report) {
this.reports.add(report);
}
}
게시글 수정 기능을 구현하던 중 에러가 발생하였다.
Hibernate에서 자식 객체를 삭제하거나 부모 객체와 연관성을 끊었지만, 변경 내용을 아직 저장하지 않은 경우 발생한다.
기존
/** 게시글 수정 */
@Transactional
public Long update(Long postId, PostUpdateRequestDto updateRequestDto) {
Post findPost = postRepository.findById(postId).orElseThrow(() -> new IllegalArgumentException("해당 글이 없습니다. id=" + postId));
List<Youtube> youtubes = youtubeRepository.findByPost(findPost);
for (Youtube youtube : youtubes) {
youtubeRepository.delete(youtube);
}
if (updateRequestDto.getReference().size() > 0) {
ArrayList<String> list = updateRequestDto.getReference();
for (int i = 0; i < list.size(); i++) {
youtubeRepository.save(updateRequestDto.toEntity(findPost, list.get(i)));
}
youtubes = youtubeRepository.findByPost(findPost);
} else {
youtubes = null;
}
findPost.update(updateRequestDto.getTitle(), updateRequestDto.getSummary(), updateRequestDto.getContent(), youtubes);
return postId;
}
변경
/** 게시글 수정 */
public Long update(Long postId, PostUpdateRequestDto updateRequestDto) {
Post findPost = postRepository.findById(postId).orElseThrow(() -> new IllegalArgumentException("해당 글이 없습니다. id=" + postId));
List<Youtube> youtubes = youtubeRepository.findByPost(findPost);
findPost.getYoutubes().clear();
List<Youtube> youtubeList = new ArrayList<>();
if (updateRequestDto.getReference().size() > 0) { //유튜브 링크가 있는 경우
ArrayList<String> list = updateRequestDto.getReference();
//Post 엔티티의 유튜브 컬렉션에 유튜브 엔티티 추가
for (int i = 0; i < list.size(); i++) {
Youtube saveYoutube = youtubeRepository.save(updateRequestDto.toEntity(findPost, list.get(i)));
youtubeList.add(saveYoutube);
}
findPost.update(updateRequestDto.getTitle(), updateRequestDto.getSummary(), updateRequestDto.getContent(), youtubeList);
} else {
findPost.update(updateRequestDto.getTitle(), updateRequestDto.getSummary(), updateRequestDto.getContent());
}
return postId;
}
코드를 위처럼 수정하였지만, 여전히 같은 문제가 발생했다.
컬렉션을 clear()로 비우면 연관관계가 끊어지고 컬렉션에 새로운 객체가 들어온 후 플러시가 되면 원래 들어있던 객체는 관계가 끊어졌기 때문에 db에서도 삭제되고 변경된 내용은 저장이 될 줄 알았다.
컬렉션을 비웠지만 플러시를 하지 않은 상태로 내용이 변경되었기 때문에 고아 객체 제거는 적용 되지 않는 것 같다.
이 경우 고아 객체 제거 기능 대신 컬렉션을 비우고 직접 db에서 delete를 해줘야 할 것 같다.
최종 변경
/** 게시글 수정 */
public Long update(Long postId, PostUpdateRequestDto updateRequestDto) {
Post findPost = postRepository.findById(postId).orElseThrow(() -> new IllegalArgumentException("해당 글이 없습니다. id=" + postId));
List<Youtube> youtubes = youtubeRepository.findByPost(findPost);
findPost.getYoutubes().clear();
for (Youtube youtube : youtubes) {
youtubeRepository.delete(youtube);
}
if (updateRequestDto.getReference().size() > 0) {
ArrayList<String> list = updateRequestDto.getReference();
//Post 엔티티의 유튜브 컬렉션에 유튜브 엔티티 추가
for (int i = 0; i < list.size(); i++) {
Youtube saveYoutube = youtubeRepository.save(updateRequestDto.toEntity(findPost, list.get(i)));
findPost.addYoutube(saveYoutube);
}
}
findPost.update(updateRequestDto.getTitle(), updateRequestDto.getSummary(), updateRequestDto.getContent());
return postId;
}