프로젝트/크루트

CascadeType.REMOVE와 orpahnRemoval=True

발전생 2022. 2. 21. 18:22

엔티티의 리스트 필드에 CascadeType.ALL을 적용한 뒤 손수 remove를 호출해줬으나 제거에 실패했다. 아래 사진처럼 말이다. 같은 stack_id, user_id 값이 두 개 있다.

CascadeType.REMOVE는 부모 엔티티가 완전히 제거됐을 때 자식 엔티티 또한 제거되는 역할을 한다. 

단지 리스트에서 제거한다고 자식 엔티티가 제거되는 것이 아니다. 

그래서 orphanRemoal = True를 추가해줬다.

 

이번에는 또 다른 에러를 만나게 된다.

A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance

 

userService에서 list를 변경해주는 코드에 문제가 있었다. 이 에러는 새로운 빈 리스트에 값을 채운 뒤 그 리스트로 엔티티의 필드를 대체할 때 만날 수 있다.

jpa가 dirty checking 할 때 새로운 리스트도 잘 읽고 반영해줄 것이라 추측했지만 그렇지 않았다.

엔티티의 필드에 새로운 리스트(hashcode 등을 통해 다르게 인식되는)가 들어오면 더 이상 jpa가 추적을 못 하는 것 같다.

 

그래서 내용만 비워주고 기존에 존재하던 리스트를 이용하는 방식으로 코드를 짰다.

 

        User user = userRepository.findById(userId).get();
        user.getUserStacks().clear();
        for (Stack stack : stacks) {
            user.getUserStacks().add(new UserStack(user, stack));
        }
        return user.getUserStacks().stream().map(userStack -> userStack.getStack() ).collect(Collectors.toList());

 

 

이제는 테이블에서 잘 제거됐다