본문 바로가기

FastCampus - 한번에 끝내는 Java|Spring 웹 개발/04 JPA

JPA Ch 8 remove cascade / soft delete - 패스트캠퍼스 챌린지 37일차

아직 살아있는 sftblw-chan 입니다. 몸 상태가 메롱해서 체온이 38도 근처로 올라갔다 내려갔다 아슬아슬하긴 한데 아직 쓰러질 정도는 아니라서 실습은 빼고 간단히 동영상만 보고 정리나 해두려구요.

REMOVE cascade 옵션

저번 강의에서 추가해놨던 cascade = Cascade.ALL 을 다시 PERSIST와 MERGE로 원상복구한 뒤에, book 만 지웁니다. 당연히 publisher 가 남아있습니다. 여기에 REMOVE를 넣으면 book을 지우면 연결된 publisher 도 같이 지워짐을 확인할 수 있습니다.

REMOVE 의 cascade 대상이 다른 것과도 연결된 경우

아.. .이건 코드 열어서 강의내용을 확인을 해봐야겠네... (귀차니즘에 애도를) 좀 강의에서 확실히 짚어주셨으면 좋았을텐데... 근데 이렇게 뱀 기어가듯 지나가서 손수 확인을 해봐야 하는 것도 좋은 거 같아요. 강제공부자너...

book1과 book2가 같은 publisher 인 publisher1 에 둘 다 연결되어 있는 경우의 cascade 를 봅니다.

테스트 코드

    private Book putBookWithName(String name) {
        상상에 맡깁니다
    }
    private Publisher putPublisherWithName(String name) {
        상상에 맡깁니다
    }
    private void bookByPublisher(Book book, Publisher publisher) {
        상상에 맡깁니다
    }

    @Test
    @Transactional
    void bookRemovalTest() {
        Book book1 = putBookWithName("book1");
        Book book2 = putBookWithName("book2");
        Book book3 = putBookWithName("book3");

        Publisher publisher1 = putPublisherWithName("pub1");
        Publisher publisher3 = putPublisherWithName("pub3");

        bookByPublisher(book1, publisher1);
        bookByPublisher(book2, publisher1);
        bookByPublisher(book3, publisher3);

        bookRepo.delete(book1); // cascade REMOVE

        System.out.println(bookRepo.findAll());
        System.out.println(pubRepo.findAll());
    }

book.publisher 에만 cascade = REMOVE 가 되어있는 경우, book1 을 지우면

  • book1과 연관된 것들
    • publisher1 삭제... 되지 않음 (book2 와 연결되어 있어서 그런가봄)
    • book2 생존
  • 대조군인 book3, publisher3 생존

publisher.books 에도 cascade = REMOVE 가 되어있는 경우, book1 을 지우면

  • 예상대로 book1 -> publisher1 -> book2 모두 삭제됩니다.
  • 대조군인 book3, publisher3 만 남음

OrphanRemoval 기능

cascade 가 지정되는 어노테이션들 중 (강의에는 안 나오지만 확인해보니) @OneTo* 계열에는 orphanRemoval 이라는 속성이 있습니다. 별 건 아니고 해당 필드에 null 을 설정해서 관계가 지워진 채로 update가 될 때, 연결된 객체가 고아가 되면 같이 지워버릴지의 옵션입니다. cascade REMOVAL 이랑의 차이는 delete() 가 아니라 save() 로 저장되었을 때 일어난다는 점이겠네요.

(Optional) Whether to apply the remove operation to entities that have been removed from the relationship and to cascade the remove operation to those entities.

아마, 제대로 이해했다면, 위의 예시 상황을 가정해본다면 Publisher 의 리스트에서 Book 을 제거하고 Publisher 를 제거하면 Book 도 같이 제거가 되어야... 책은 출판사 없이는 있을 수 없다- 이런 상황에서만 쓰는 모양입니다.

강의 중간에 스프링 공식 문서를 가져왔다면서 아래 내용을 붙여넣기해서 보여주시는데 아무리 찾아도 스택오버플로우밖에 안 나옵니다... 아무튼 아래 S/O가 이해하는데 도움은 되니까요.
https://stackoverflow.com/a/18815984

그런...에 웬걸 이거 암만 테스트해도 의도한 대로 안 돌아가네요. 슬프게도 강의에서도 그냥 이런 게 있다 정도만 하고 넘어가서, 강의를 보고 검증할 수도 없고 왜 안 되는지 테스트해볼 시간도 없네요...

소프트 딜리트

엔터프라이즈 애플리케이션에서 엔티티를 삭제할 때 진짜로 delete 쿼리를 실행하는 일은 드뭅니다. 거기에 "삭제됨" 이라도 남겨놔야 할 거 아니에요. 히스토리도 남겨야 하고... 그래서 엔티티에 private boolean deleted = false; 필드를 두는 경우가 많다네요.

그냥 놔두면 delete 로 마킹된 것들도 나오므로, 엔티티에 @Where 어노테이션을 달아주면 됩니다. 그러면 각종 메서드에서 실행하는 쿼리문의 where 부분에 들어간다네요.

@Entity
생략
@Where(clause = "deleted = false")
public class Book extends BaseAuditingEntity {
    생략
    private boolean deleted = false;

어노테이션은 보니까 hibernate 꺼더라구요.

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.
패스트캠퍼스: https://bit.ly/37BpXiC

#패스트캠퍼스 #패캠챌린지 #직장인인강 #직장인자기계발 #패스트캠퍼스후기 #한번에끝내는JavaSpring웹개발마스터초격차패키지Online

오늘이 아기다리고기다리던 모바일게임 명일방주의 이벤트 위기협약 #6 와일드 스케일의 개방일인데... 몸 상태가 영 안 좋아서 하다가 피곤해서 침대행을 할 수 밖에 없었다능; 덕분에 패캠챌린지도 한 풀 꺾인 상태로 할 생각이었는데, 한 풀 꺾였어도 확인할 부분은 확인해야겠다 싶더라구요. "저런"에 "저런"입니다 진짜.