1 분 소요

spring bot test 코드를 작성하고, 실행하는 중에 문제가 발생했다.

` org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist `

기존에 Postman으로 테스트를 할 때에는 문제가 없었는데, test 코드를 작성하여 실행하니 문제가 발생했다.

서핑을 해보니 아래의 블로그 게시글이 보였다.

https://abbo.tistory.com/276 https://bottom-to-top.tistory.com/24

결론적으로 cascade의 문제였다. cascade를 다시 살펴보면 아래와 같다.

Cascade Type

  • CascadeType.ALL
    • 모든 Cascade를 적용한다.
  • CascadeType.RESIST
    • 엔티티를 생성하고, 연관 엔티티를 추가했을 때 persist()를 수행하면 연관 엔티티도 함께 persist()가 수행된다. 만약 연관 엔티티가 DB에 등록된 키값을 가지고 있다면 deatched entity passed to persist Exception이 발생한다.
  • CascadeType.MERGE
    • 트랜잭션이 종료되고 detach 상태에서 연관 엔티티를 추가하거나 변경된 이후에 부모 엔티티가 merge()를 수행하게 되면 변경사항이 적용된다. (연관 엔티티의 추가 및 수정 모두 적용된다.)
  • CascadeType.REMOVE
    • 삭제 시 연관된 엔티티도 같이 삭제된다.
  • CascadeType.DETACH
    • 부모 엔티티가 detach()를 수행하게 되면, 연관된 엔티티도 detach() 상태가 되어 변경사항이 반영되지 않는다.

우선 본인의 경우 완전히 잘 못 사용했다.

필드 구성

image

그룹별로 게시글을 작성할 수 있고, 그룹이 삭제될 때 게시글이 함께 삭제되고, 첨부파일도 함께 삭제시키고자 했다. 다만 Cascade를 잘못된 필드에서 사용했다.

Post.java의 코드 일부분이다.

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "group_id", nullable = false, updatable = false)
    private Group group; // post를 올릴 group

cascade가 Group이 아닌 Post에 적용되어 있다. 이로 인해 게시글이 삭제될 때 그룹이 삭제되는 기이한 코드가 되어버렸다.

코드 수정

기존의 Group과 Post Entity를 수정한다.

GitHub Group.java 변경점 보기

@OneToMany(mappedBy = "group", cascade = CascadeType.REMOVE)
    private List<Post> posts = new ArrayList<>();

위의 내용을 추가했다. 이를 통해 1:N을 이루고, Group이 삭제될 때 Post도 함께 사라지도록 Cascade도 설정했다.

GitHub Post.java 변경점 보기 기존에는 cascade = CascadeType.ALL이었는데, 의도한 목적에 맞게 cascade = CascadeType.REMOVE으로 수정했다.

문제 해결 완료

해당 작업을 통해 의도와 다르게 작동하는 코드를 수정하고, 기존에 누락된 기능도 추가하였다. (그룹을 삭제할 때 포스트도 함께 삭제하는 기능이 누락되어 있었다…)