프록시
- 연관관계에 있는 엔티티의 데이터를 제외하고 하나의 엔티티의 데이터만 가져올 수 있을까?
- 연관관계에 있는 엔티티의 데이터를 한번의 조회로 가져오면 효율적이지 않을까?
- find() : 데이터베이스를 통해 실제 엔티티 객체를 조회
- getReference() : 데이터베이스 조회를 미루는 프록시 (가짜) 엔티티 객체를 조회
프록시 원리
- 프록시 객체는 실제 객체의 참조(target) 보관
- 실제 클래스를 상속 받는다.
- 사용 시에는 진짜 객체인지 프록시 객체인지 구분하지 않고 사용 가능하다.
- 프록시 객체의 초기화
프록시 객체에 값 조회시에 영속성 컨텍스트에 초기화를 요청하여 target을 이용하여 실제 객체를 연결해준다.
프록시 특징
- 프록시 객체는 처음 사용할 때 한 번만 초기화된다.
- 프록시 객체를 초기화 할 때, 프록시 객체가 실제 엔티티로 바뀌는게 아니라 실제 엔티티에 접근이 가능하게 해준다.
- 프록시 객체는 원본 엔티티를 상속받으므로 'instance of'로 비교해야한다.
- 영속성 컨텍스트에 찾는 엔티티가 이미 존재하면 실제 엔티티를 반환한다.
- 반대로 프록시 먼저 조회한 뒤에 실제 객체를 반환해도 프록시 객체를 반환해준다.
- JPA는 하나의 트랜잭션 내에서는 동일함을 보장해준다.
- 준영속 상태일 경우에는 프록시 초기화시 에러가 발생한다.
즉시로딩과 지연로딩
- 연관관계에 있는 데이터도 한꺼번에 조회해야 하는가?
- 지연로딩이라는 옵션을 제공한다. (fetch = FetchType=LAZY)
- 지연로딩 설정시 프록시로 조회한다.
- 프록시 객체 사용시에 초기화 시작
- 즉시로딩 (fetch = FetchType=EAGER)
가급적 지연 로밍만 사용한다.
- 즉시로딩 사용시 예상치 못한 SQL이 발생한다.
- 즉시로딩은 JPQL에서 N+1 문제를 일으킨다.
- 해결 방법 : JPQL fetch 조인 / 엔티티 그래프 기능
- @ManyToOne, @OneToOne의 기본은 즉시로딩이므로 LAZY로 설정해줘야 한다.
- @OneToMany, @ManyToMany의 기본은 지연로딩이다.
영속성 전이 (CASCADE)
- 특정 앤티티를 영속 상태로 만들때 연관된 엔티티도 함께 영속 상태로 만들고 싶을 경우에 사용한다.
고아 객체
- 부모 엔티티와 연관관계가 끊어진 객체를 삭제하는 가능
- 참조하는 곳이 하나일 경우 사용한다.
- @OneToOne / @OneToMany 일때 사용한다.
CASCADE와 고아 객체 기능 활용시에 부모 엔티티로 자식 엔티티를 관리할 수 있다.
-> CASECADE 및 고아객체 관련하여 현재 그냥 개념이 있다 정도만 아는 상태로, 공부가 더 필요하다.