[자바 ORM 표준 JPA 프로그래밍] 8. 프록시와 연관관계 관리

서요이·2022년 11월 30일
0
post-thumbnail

8. 프록시와 연관관계 관리

프록시

  • em.find(): 데이터베이스를 통해서 실제 엔티티 객체 조회 - 쿼리 O
  • em.getReference(): 데이터베이스 조회를 미루는 가짜(프록시) 엔티티 객체 조회 - 쿼리 X

프록시 특징

  • 실제 클래스 상속받아서 생성, 겉 모양이 같음
  • 사용자 입장에서는 진짜 객체인지 프록시 객체인지 구분하지 않고 사용
  • 프록시 객체는 실제 객체의 참조를 보관
  • 프록시 객체 호출 → 실제 객체의 메소드 호출 (위임)

초기화: Member member = em.getReference(Member.class, "id1");

  • 처음 사용할 때 한 번만 초기화
  • 초기화 시 프록시 객체가 실제 엔티티로 바뀌는 것은 X
  • 프록시 객체는 원본 엔티티 상속받음 → 타입 체크시 주의!! (== 대신 instance of 사용)
  • 영속성 컨텍스트에 이미 엔티티가 있으면 em.getReference() 호출해도 실제 엔티티 반환
  • 준영속 상태일 때 프록시 초기화 → 문제 발생

프록시 확인

  • 프록시 인스턴스의 초기화 여부 확인
    PersistenceUnitUtil.isLoaded(Object entity)
  • 프록시 클래스 확인 방법
    entity.getClass().getName()
  • 프록시 강제 초기화
    org.hibernate.Hibernate.initialize(entity)

즉시 로딩과 지연 로딩

  • 지연 로딩 LAZY를 사용해서 프록시로 조회 @ManyToOne(fetch = FetchType.LAZY) 객체를 가져올 때가 아닌 객체를 사용하는 시점에 초기화(쿼리)
  • 즉시 로딩 EAGER를 사용해서 Member와 Team 항상 함께 조회 @ManyToOne(fetch = FetchType.EAGER)

프록시와 즉시 로딩 주의

  • 가급적 지연 로딩만 사용(실무)
  • 즉시 로딩은 JPQL에서 N+1 문제 일으킴
  • @ManyToOne, @OneToOne은 기본이 즉시 로딩 -> LAZY로 설정

지연 로딩 활용

  • Member, Team 자주 함께 사용 → 즉시 로딩
  • Member, Order 가끔 사용 → 지연 로딩
  • Order, Product 자주 함께 사용 → 즉시 로딩

실무에서는 모든 연관관계에 지연 로딩 사용, 즉시 로딩 사용 X

영속성 전이: CASCADE

특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로

@OneToMAny(mappedBy="parent", cascade=CascadeTypePERSIST)

주의: 영속성 전이는 연관관계 매핑과 관련 X, 단지 편리함 제공

CASCADE의 종류

  • ALL: 모두 적용
  • PERSIST: 영속
  • REMOVE: 삭제
  • MERGE: 병합
  • REFRESH: REFRESH
  • DETACH: DETACH

고아 객체

고아 객체 제거: 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제

orphanRemoval = true

주의: 참조하는 곳이 하나일 때 사용! 특정 엔티티가 개인 소유할 때 사용

고아 객체 제거 활성화 시 부모를 제거할 때 자식도 함께 제거됨(=CascadeType.REMOVE)

영속성 전이 + 고아 객체, 생명주기

CascadeType.ALL + orphanRemoval=true

두 옵션을 모두 활성화 하면 부모 엔티티를 통해서 자식의 생명 주기를 관리할 수 있음

0개의 댓글