프록시와 연관관계 관리

강한친구·2022년 7월 12일
0

JPA

목록 보기
10/27

꼭 같이 출력해야할까

다대일관계에 있는 Member, Team 테이블이 있을때, Member를 조회할 때, 이를 꼭 같이 출력해야 하는걸까?

프록시 기초

em.find() : 데이터베이스를 통해 진짜 entity를 조회한다
em.getReference() : 데이터베이스 조회를 미루는 프록시 엔티티 조회

프록시 엔티티?

프록시는 실제 클래스를 상속받아서 만들어지고, 실제 클래스와 모양이 같아서 사용하는 입장에서는 구분할 필요 없이 쓰면 된다(이론상)

프록시는 실제 객체의 참조(target)을 보관한다. 프록시 객체를 호출하면 실제 객체의 메소드를 호출하게 된다.

작동원리는 다음과 같다.

출처 : 김영한님의 JPA 강의

프록시의 특징

  • 최초사용시 1회만 초기화한다. 프록시 객체를 초기화 할 때, 실제 엔티티가 되는것이 아니라 초기화를 통해서 target 클래스에 접근하는것이다.

  • 영속성 컨텍스트에 엔티티가 이미 있으면, em.getReference를 호출해도 실제 원본 엔티티가 나온다

  • proxy를 detach, clear 처리를 하면 영속성 컨텍스트가 끝나게 된다. 이때, proxy를 통해서 메서드를 실행하면 영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태가 되고 이때, 프록시를 초기화하면 문제가 발생한다.
    하이버네이트는 org.hibernate.LazyInitializationException 예외를 터트린다.

하이버네이트를 사용하면 강제로 초기화 할 수 있다. org.hibernate.Hibernate.initialize(entity);
하지만 getRef기능 자체를 잘 쓰지는 않는다.

이제 최초의 질문인 같이 조회해야 하는가로 돌아가봐야 한다.

지연로딩

Lazy 세팅 즉, 엔티티가 지연로딩이 세팅이 되어있으면, 프록시로 가지고 오게 된다.
Member를 가지고 올때, 지연로딩 세팅이 되어있으면 각각 member와 team은 프록시로 호출된다.
이때, 메소드로 member의 무엇인가를 호출하면 그때 member가 초기화되고 호출된다. team은 호출이 없었기에, 프록시로 그대로 남아있게 된다.

즉시로딩

Eager 옵션을 쓰면, 가지고 em.find로 가지고 올 때 부터 바로 가지고 와서 같이 쓴다.

주의사항

실무에서는 가급적 지연로딩을 써야한다.
1, 즉시로딩을 적용하면 예상밖의 sql이 발생하게 된다.
2. JPQL에서 N+1 문제가 발생한다

  • jpql에서는 내가 쓴 쿼리문을 sql로 번역해서 보내는 기능이다. 이때 즉시로딩으로 설정이 되어있으면, 맴버쿼리가 나가고, 즉시로딩으로 설정된 Team의 정보도 꺼내와야하는 상황에 처한다. 따라서 맴버의 개수만큼 가지고 오려고 쿼리가 또 나가게 된다.
  1. 만약 Lazy 설정을 하고도 한번에 꺼내와야하면, fetch join같은 방법을 쓰면 된다.

• @ManyToOne, @OneToOne은 기본이 즉시 로딩
-> LAZY로 설정
• @OneToMany, @ManyToMany는 기본이 지연 로딩

영속성 전이와 고아객체

영속성 전이(cascade)

특정 엔티티를 영속상태로 만들 때, 연관 엔티티까지 전부 영속화하고 싶을때 사용하는 기능이다.
예: 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장

cascade의 종류

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

언제쓰는가?

Child가 Parent에서만 관리가 될때, 즉 소유자가 하나고 해당 엔티티가 하나의 엔티티와 연관관계를 맺을 때는 쓰는것이 좋지만, 그렇지 않은 경우는 안쓰는게 좋다.

고아객체

부모 엔티티와 관계가 끊어진 자식 엔티티를 자동 삭제하는 기능이다.
부모 엔티티에 orphanRemoval = true를 넣어두면, 참조가 제거되는 순간 바로 삭제된다.

위의 기능과 마찬가지로 참조하는곳이 하나이고, 특정 엔티티가 개인소유일때만 사용해야한다.

또한 @OneToOne, @OneToMany만 가능하고, 부모가 삭제되면 자식도 알아서 삭제된다.

0개의 댓글