인프런 커뮤니티 질문&답변

파이팅파이팅님의 프로필 이미지

작성한 질문수

자바 ORM 표준 JPA 프로그래밍 - 기본편

영속성 컨텍스트 2

(fetch=FetchType.LAZY,cascade = CascadeType.ALL)에 관해 질문 있습니다.

24.07.08 00:52 작성

·

108

0

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.

1. 강의 내용과 관련된 질문을 남겨주세요.
2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.
(자주 하는 질문 링크: https://bit.ly/3fX6ygx)
3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.
(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)

질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.
=========================================
[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예/아니오)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)

[질문 내용]
안녕하세요 김영한 강사님 항상 강의 잘 보고 있습니다.

다름이 아니라, 연관 관계를 맺고 있는 엔티티들 사이에서 (fetch=FetchType.LAZY,cascade = CascadeType.ALL)에 대해 질문 있습니다.

예를 들어,

public class Site {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="site_id")
    private Long id;

    @Column(name="site_name")
    private String siteName;

    @Column(name="site_url")
    private String siteUrl;

    @ManyToOne(fetch=FetchType.LAZY,cascade = CascadeType.ALL)
    @JoinColumn(name="directory_id")
    private Directory directory;

public class Directory {

    @Id@GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="directory_id")
    private Long id;

    @Column(name="directory_name")
    private String directoryName;

    @OneToMany(mappedBy="directory", cascade = CascadeType.ALL,orphanRemoval = true)
    private List<Site> sites = new ArrayList<>();

에서 directory와 site가 1:N 연관 관계를 맺고 있습니다.

예를 들어, 클라이언트로부터 directory를 조회하는 요청이 온다면 다음과 같이 수행된다고 이해를 하고 있습니다.

  1. db에 접근해서 directory를 조회함.

  2. 해당 directory entity를 영속성 컨텍스트에 저장함.

  3. 이때, fetch=FetchType.LAZY를 사용하고 있기 때문에,
    쿼리문을 날릴 때, site를 조회하는 쿼리문을 날리는게 아니라 directory만 조회하는 쿼리문을 날림

  4. 그리고 directory 필드에 있는 site는 기본 생성자를 통해
    프록시 객체로 생성되어 저장됨.

근데, 여기서 헷갈리는게 그렇다면 "cascade = CascadeType.ALL"는 언제 어떻게 사용되는 것인지 잘 모르겠습니다.

제가 "cascade = CascadeType.ALL"에 대해서 이해하기로는 부모 엔티티와 자식 엔티티를 라이프 싸이클을 동일하게 가져가기 위해서 부모 엔티티가 영속화될 때 자식 엔티티도 같이 영속화 된다. 라는 정도로 이해하고 있습니다.

근데, 여기서 헷갈리는 부분이

directory를 조회하고, directory의 필드로 있는 site는 fetch=FetchType.LAZY로 설정했기 때문에 프록시 객체로 생성됩니다.
그렇다면 이때 site는 directory와 관련된 실제 데이터가 저장되어 있는 객체가 아니라 빈 껍데기같은 객체가 되는게 아닌가요??

그러면 directory랑 site가 "cascade = CascadeType.ALL로 설정해서 부모 엔티티와 자식 엔티티를 라이프 싸이클을 동일하게 가져간다"라는게 틀린게 되는게 아닌가요??

fetch=FetchType.LAZY,cascade = CascadeType.ALL이 2개를 같이 사용했을 때, 엔티티를 생성,조회 그리고 삭제 하는등의 동작을 수행할 때, 어떻게 동작되는지 연관성과 차이점을 잘 모르겠습니다 ..

매번 훌륭한 강의 감사합니다

답변 2

0

김영한님의 프로필 이미지
김영한
지식공유자

2024. 07. 10. 20:13

안녕하세요. 파이팅파이팅님

다음 질문을 보시면 cascade와 mappedBy는 서로 관계가 없는데요.

https://www.inflearn.com/questions/15855

마찬가지로 LAZY와 Cascade도 서로 관련이 없는 기능으로 분리해서 이해하시면 됩니다 🙂

감사합니다.

0

인프런 AI 인턴님의 프로필 이미지

2024. 07. 08. 00:56

안녕하세요, 인프런 AI 인턴입니다.

파이팅파이팅님, JPA의 fetch=FetchType.LAZYcascade = CascadeType.ALL에 대해 질문해주셨네요. 이 두 옵션의 차이점과 연관 관계에서의 역할에 대해 알아보겠습니다.

  1. fetch=FetchType.LAZY: 지연로딩을 설정하는 옵션입니다. 지연 로딩을 사용하면, 관계가 맺어진 엔티티를 실제로 사용하는 시점에 조회(데이터베이스 접근)를 합니다. 즉, 부모 엔티티를 조회할 때 자식 엔티티는 프록시 객체로 초기화되어 있고, 해당 자식 엔티티에 실제로 접근하는 순간에 DB에서 데이터를 로드합니다. 이는 성능 최적화 측면에서 중요한 옵션입니다.

  2. cascade = CascadeType.ALL: 영속성 전이를 설정하는 옵션입니다. 부모 엔티티의 생명주기(생성, 삭제, 업데이트 등)가 자식 엔티티에 전파됩니다. 예를 들어, 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장되고, 부모 엔티티를 삭제할 때 자식 엔티티도 함께 삭제됩니다. 이는 관계가 있는 엔티티들 간의 라이프사이클을 관리하는 데 필요합니다.

질문하신 상황에서 directory를 조회할 때 site는 실제 데이터를 로드하지 않고 프록시 객체로 남아 있습니다. 즉, directory에 대한 쿼리만 실행되고, site에 대한 데이터는 접근할 때까지 로드되지 않습니다. 이는 지연 로딩 설정 때문입니다.

cascade = CascadeType.ALL 설정은 directorysite의 라이프사이클을 연동시키지만, 데이터를 즉시 로드하지는 않습니다. 예를 들어, directory를 저장하거나 삭제할 때 site 목록도 함께 저장되거나 삭제됩니다. 하지만 이러한 영속성 전이는 데이터 로드와는 별개의 개념입니다.

지연 로딩(FetchType.LAZY)은 데이터를 언제 로드할지 결정하는 반면, 영속성 전이(cascade)는 하나의 엔티티에 대한 연산이 관련 엔티티에 어떻게 전파되는지를 결정합니다. 따라서 이 두 설정은 서로 다른 관점에서 엔티티 간의 관계를 관리합니다.

바로가기: JPA 영속성 전이(CASCADE)와 고아 객체에서 더 자세한 설명을 찾을 수 있습니다. 이 질문과 답변은 영속성 전이와 관련하여 다른 사례를 설명하고 있습니다. 그 외에도, 강의 내용에서 영속성 전이와 지연 로딩에 대한 더 많은 사례와 사용 예시를 찾아볼 수 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.