프록시와 연관관계 관리

개발하는 도비·2023년 4월 29일

JPA

목록 보기
6/13
post-thumbnail

프록시란?

프록시 기초

  • em.find() vs em.getReference()
    • em.find() : 데이터베이스를 통해서 실제 entity 객체 조회
    • em.getReference() : 데이터베이스 조회를 미루는 프록시 entity 객체 조회
      • em.getReference() 호출 시점에는 쿼리를 보내지 않음.
      • em.getReference() 불러온 값을 사용할 때 쿼리를 보냄.

프록시 특징-기본

  • 실제 클래스를 상속 받아서 만들어짐
  • 실제 클래스와 겉 모양이 같다. -> 값은 비워져 있음
  • 사용시 진짜 객체인지 프록시 객체인지 구분하지 않고 사용

프록시 특징-객체 초기화

  • 객체 초기화 순서

    • 프록시 객체 생성 -> 초기화 요청 -> DB 조회 -> 실제 Entity생성 -> 초기화된 값 반환
  • 특징

    • 프록시 객체는 처음 사용할 때 한번 초기화 -> 이후에 사용할 경우 초기화 되지 않음.
    • 초기화 -> 실제 entity로 바뀌는게 아님. 프록시 객체에 값이 채워진 것
      • 따라서 타입 비교시 ==이 아닌 instance of 사용.
    • JPA는 한 영속성 컨텍스트의 가져올 경우 ==을 보장해 줘야하기에 생기는 특징
      • em.find() -> em.getReference()의 경우 실제 entity를 가져옴
      • em.getReference() -> em.find()의 경우 프록시를 반환
    • 준영속 상태일 때, 프록시를 초기화하면 문제 발생
      • em.close(), em.detach() 상태일 때 초기화할 수 없음.

프록시 확인-method

  • 프록시 인스턴스의 초기화 여부 확인
    • PersistenceUnitUtil.isLoaded(Object entity)
  • 프록시 클래스 확인
    • entity.getClass().getName()
  • 프록시 강제 초기화
    • org.hibernate.Hibernate.initialize(entity);
  • 참고: JPA 표준은 강제 초기화 없음
    • 강제 호출: entity.getName()

지연 로딩, 즉시 로딩

지연 로딩

  • em.find() -> entity 내부 entity를 사용 -> 해당 시점에 내부 entity를 초기화
  • 예시
    Team team = member.getTeam();
    team.getName(); // 실제 team을 사용하는 시점에 초기화(DB 조회)

즉시 로딩

  • em.find()에서 모두 초기화
  • fetch = FetchType.EAGER 로 사용

실무 적용

  • 가급적 지연 로딩만 사용
    • 예상치 못한 SQL이 발생
    • JPQL에서 N+1 문제 발생 -> em.createQuery 사용시
      • 쿼리 -> 확인 해보니 내부 entity 존재 -> 다시 쿼리
      • 즉 처음 쿼리 1 + 내부 entity로 인한 N번의 쿼리 발생.
    • @ManyToOne, @OneToOne은 기본이 즉시 로딩 -> fetch = FetchType.LAZY 사용
    • @OneToMany, @ManyToMany는 기본이 지연 로딩

영속성 전이: CASCADE

  • 특정 entity를 영속 상태로 만들 때 연관된 entity도 함께 영속 상태로 만들도 싶을 때 사용.
  • cascade=CascadeType.TYPE
    • ALL: 모두 적용
    • PERSIST: 영속
    • REMOVE: 삭제
    • MERGE: 병합
    • REFRESH: REFRESH
    • DETACH: DETACH
  • 주의점
    • 연관관계를 매핑하는 것이 아님.
    • 영속화를 편하게 함을 제공.
    • 소유지가 하나일 경우 사용. -> 즉 하나의 entity의 종속적일 때.

고아 객체

  • 부모 엔티티와 연관관계가 끊어진 자식 엔티티 를 자동으로 삭제
  • orphanRemoval = true
  • 주의
    • 참조하는 곳이 하나일 때.
    • 특정 entity가 개인 소유할 때
    • @OneToOne, @OneToMany만 가능

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

  • CascadeType.ALL + orphanRemoval=true
  • 부모 엔티티를 통해서 자식의 생명 주기를 관리

참조

  • 인프런 : 자바 ORM 표준 JPA 프로그래밍 - 기본편
  • 링크
profile
도비의 양말을 찾아서

0개의 댓글