프록시와 연관관계

동현·2021년 7월 29일
0

프록시와 연관관계 관리

  • 프록시와 지연로딩, 즉시로딩
  • 영속성 전이와 고아 객체

프록시

엔티티 조회시 늘 연관된 데이터가 사용되는 것은 아니다.

그렇다면 가-나-다 로 연관이 맺어져 있는 엔티티가 있을때 가 를 조회나- 다를 사용하지 않는데

전부다 불러오는게 맞는 것일까?

→ 이는 서버에 부하를 주게 되는 행위이다 따라서 이를 예방하기 위해 지연로딩, 즉시로딩, 프록시가 존재한다.

그렇다면 프록시는 무엇일까?

프록시란 지연로딩 사용중 실제 엔티티 객체 대신 데이터 베이스 조회를 지연시킬수 있게 도와주는 가짜 객체를 프록시라 한다.

Member member = em.find(Member.class, "member1");

위와 같이 member를 조회하는 경우 member와 Team이 연관관계가 있다면 지연로딩을 하지 않을 경우에는 Team의 사용여부와 상관 없이 Team까지 같이 불러오게 된다.

이를 프록시를 사용하여 사용 시점까지 조회를 미루고 싶다면 다음 코드를 사용하면 된다.

Member member = em.getReference(Member.class, "member1");

프록시의 특징

프록시 클래스는 실제 클래스를 상속 받아서 생성되므로 실제 클래스와 겉 모습이 같다.

→ 사용자는 가짜 객체인지 진짜 객체인지 신경쓰지 않고 사용해도 무방하다.

  • 프록시 객체는 처음 사용할 때 한번만 초기화
  • 프록시 객체를 초기화 한다해서 프록시 객체가 실제 엔티티로 바뀌는 것은 아니다. (프록시 객체를 통해 실제 객체에 접근이 가능한 것)
  • 영속성 컨텍스트에 이미 찾는 데이터가 있다면 데이터 베이스를 조회 할 필요가 없다. 이때는 프록시가 아닌 실제 엔티티 객체를 반환
  • 초기화는 영속성 컨텍스트에 도움을 받아야 가능하기 때문에 준영속 상태의 프록시는 초기화시 문제가 발생한다.

☝️ 프록시는 실제 객체에 대한 참조를 보관하기 때문에 프록시 객체 메소드를 호출하게 되면 실제 객체의 메소드를 호출하게 된다. 이를 초기화라고도 한다.

➕ 프록시 객체는 식별자 값을 가지고 있기때문에 team.getId()를 하여도 초기화가 되지 않는다.

➕PersistenceUnitUtil.isLoaded(Object entity) 메소드를 사용시 인스턴스 초기화 여부를 확인 가능.


즉시 로딩과 지연 로딩

  • 즉시로딩 : 엔티티 조회시 연관 엔티티 모두 조회 (@ManyToOne(fetch = FetchType.EAGER)
  • 지연 로딩 : 연관된 엔티티를 실제 사용할때 조회 (@ManyToOne(fetch = FetchType.LAZY)

지연 로딩

LAZY LOADING을 사용하게 되면 회원 - 팀을 지연 로딩 설정시 회원을 조회 하게 되면 회원의 팀은 프록시 객체로 조회가 된다.

이는 사용하기 직전까지 프록시객체로 존재하며 사용시에 데이터 베이스를 조회해 초기화를 하게 된다.

(김영한 님은 즉시 로딩 보다 지연 로딩을 사용하는것을 추천한다고 하신다.)


영속성 전이 : CASCADE

특정 엔티티를 영속 상태로 만들시 연관된 엔티티를 같이 영속 상태로 만들고 싶다면 영속성 전이를 사용하면 된다.

  • JPA에서 엔티티 저장시 연관된 모든 엔티티는 영속 상태여야 한다.

영속성 전이 : 저장

CASCADE 옵션을 사용해 적용 가능하다

@OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)
  • 위 옵션을 적용하게 된다면 부모와 자식 엔티티를 한번에 영속이 가능하다.
  • 영속성 전이는 연관관계를 매핑하는것과는 관련이 없고 단지 엔티티를 영속화 할 때 연관된 엔티티도 같이 영속화하는 편리함을 제공한다.

영속성 전이 : 삭제

CascadeType.REMOVE
  • 위 옵션을 적용하게 되면 부모 엔티티 삭제시 연관된 엔티티를 모두 삭제해 준다. (이를 설정해주지 않는다면 부모 엔티티만 삭제 되어 외래키 무결성 예외 발생)

고아 객체

JPA는 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동 삭제하는 기능을 제공한다. 이를 고아 객체라고 한다.

@OneToMany(mappedBy = "parent", orphanRemoval = true)
  • 컬렉션에 다음 옵션을 설정함으로서 고아 객체를 자동으로 삭제가 가능하다.

CASCADE.ALL + 고아 객체

두 옵션을 함께 설정시 부모 엔티티가 자식의 생명 주기를 관리가 가능하다.

profile
여긴 어디 나는 누구?

0개의 댓글