[JPA] 프록시

JUJU·2024년 7월 1일
0

Spring Boot

목록 보기
12/13
본 포스트는 김영한 개발자님의 JPA 프로그래밍 강의를 듣고 정리한 것입니다.
※ 코드는 강의에서 사용된 것과 다릅니다.
jaewon-ju Github Address

✏️ 프록시

프록시

: 엔티티의 지연 로딩을 관리하기 위해 사용하는 객체

  • 엔티티 객체에 대한 참조를 가지고 있다.
  • 프록시 객체의 메소드를 호출하면, 프로시 객체는 실제 엔티티의 메소드를 호출한다.

언제 프록시를 사용하는가?
➜ 테이블을 조회할 때, 연관관계 객체는 필요하지 않은 경우

연관되어 있는 객체를 함께 조회하려면, Join을 사용해서 테이블을 함께 조회해야 한다.
➜ 쿼리가 복잡해진다.

따라서, 비즈니스 로직에서 연관관계 객체가 필요하지 않다면 프록시를 사용한다.


■ 특징

  • 실제 엔티티를 상속받아서 만들어진다.
  • 실제 엔티티의 참조를 보관한다.
  • 프록시는 처음 사용할 때 한 번만 초기화된다.
  • em.find()는 실제 엔티티를 조회하는 메소드이고, em.getReference를 사용하면 프록시를 조회할 수 있다.

⚠️ 영속성 컨텍스트에 엔티티가 이미 존재하면, em.getReference를 호출해도 실제 엔티티를 반환한다.


■ 초기화

프록시 초기화란?

: 프록시 객체가 처음으로 실제 엔티티의 데이터에 접근할 때 발생하는 과정


Issue issue1 = em.getReference("Issue.class","issue1");
issue1.getTitle();
  1. em.getReference("Issue.class","issue1");를 호출하면, 프록시 객체인 IssueProxy를 반환한다.

  2. issue1.getTitle(); 를 호출하면, 실제 엔티티를 호출해야 한다.
    엔티티가 생성되지 않았다면, 영속성 컨텍스트에 초기화 요청을 한다.

  3. 영속성 컨텍스트는 DB에서 Issue 엔티티를 조회한다.

  4. IssueProxy 객체는 참조를 통해 Issue 객체의 getTitle() 함수를 호출한다.


⚠️ 프록시 객체가 준영속 상태인 경우, 프록시를 초기화하면 오류가 발생한다!




✏️ 즉시 로딩과 지연 로딩

■ 즉시 로딩

엔티티를 조회할 때 해당 엔티티의 연관된 엔티티들도 함께 즉시 로드하는 전략

  • @JoinColumn(fetch = FetchType.EAGER) 를 사용한다.
  • @ManyToOne, @OneToOne 은 기본 값이 즉시 로딩이다.

education_content 테이블은 menu_id 를 FK로 가지고 있다.

만약, @JoinColumn(fetch = FetchType.EAGER) 로 설정되어 있다면, education_content를 조회할 때 항상 menu도 함께 조회한다.


■ 지연 로딩

엔티티를 실제로 필요로 할 때까지 연관된 엔티티의 로딩을 지연시키는 전략

  • @JoinColumn(fetch = FetchType.LAZY) 를 사용한다.
  • @OneToMany, @ManyToMany 는 기본 값이 지연 로딩이다.

education_content 테이블은 menu_id 를 FK로 가지고 있다.

만약, @JoinColumn(fetch = FetchType.LAZY) 로 설정되어 있다면, education_content를 조회할 때 menu는 프록시 객체로 조회된다!


  • 실무에서는 가급적 지연 로딩을 사용해야 한다.
  • 즉시 로딩은 JPQL에서 N+1 문제를 일으킨다.



✏️ CASCADE

영속성 전이 (CASCADE)

: 한 엔티티에 대한 변경이 연관된 다른 엔티티에 자동으로 반영되는 기술

  • 특정 엔티티를 영속 상태로 만들 때, 연관된 엔티티도 함께 영속 상태로 만들 수 있다.
  • 두 엔티티의 라이프 사이클이 동일할 때 사용하는 것이 좋다.

■ 종류

  • CascadeType.ALL : 모든 작업(변경, 영속, 삭제 등)에 CASCADE 적용
  • CascadeType.PERSIST : 부모 엔티티를 영속화할 때 연관된 자식 엔티티도 함께 영속화
  • CascadeType.MERGE : 부모 엔티티가 병합될 때 연관된 자식 엔티티도 함께 병합
  • CascadeType.REMOVE : 부모 엔티티가 삭제될 때 연관된 자식 엔티티도 함께 삭제
  • CascadeType.DETACH : 부모 엔티티가 영속성 컨텍스트에서 분리될 때 연관된 자식 엔티티도 함께 분리
  • CascadeType.REFRESH : 부모 엔티티를 새로고침할 때 연관된 자식 엔티티도 함께 새로고침



✏️ Orphan Removal

부모 엔티티와의 관계가 끊어진 자식 엔티티를 자동으로 삭제하는 기능

  • 부모 엔티티테서 특정 자식 엔티티를 제거하는 것은, 참조를 삭제하는 것이다.
  • Orphan Removal 기능을 사용하면, 부모가 없어진 고아 객체를 DB에서도 완전히 삭제한다.

Orphan Removal은 @OneToOne, @OneToMany 에서만 사용 가능하다.


■ CASCADE + Orphan Removal

CascadeType.ALL, orphanRemoval = true 속성을 함께 사용하면, 부모 엔티티를 통해서 자식의 생명 주기를 관리할 수 있다.




REFERENCE

자바 ORM 표준 JPA 프로그래밍 - 김영한 개발자님

profile
개발자 지망생

0개의 댓글

관련 채용 정보