프록시
em.find() vs em.getReference()
em.find() : 데이터 베이스를 통해 실제 엔티티 객체 조회
em.getReference() : 데이터베이스 조회를 미루는 가짜(프록시) 엔티티 객체 조회
가짜(프록시) 엔티티 객체 조회 : DB에는 쿼리가 실행되지 않고 값을 가져옴.
find()는 사용하자마자 쿼리를 통해 조회하여 데이터를 가져옴
getReference()는 사용 당시의 쿼리를 통해 조회를 하지 않고, 실제 값이 필요로 할때
조회되도록 설정
프록시 특징
실제 클래스를 상속 받아서 생성
실제 클래스와 겉 모양이 같다.
사용자 입장에서 구분하지 않은채 사용할 수 있다.
객체는 처음 사용할 때 한번만 초기화
프록시 객체가 초기화 되어도, 실제 엔티티로 바뀌진 않고 실제 엔티티에 접근만 가능
프록시 객체는 원본 엔티티를 상속받기 때문에 타입 체크 주의 ( == 비교 실패, 대신 instace of 로 사용)
프록시와 객체는 항상 동일을 보장
프록시 객체는 실제 객체의 참조(target)를 보관
프록시 개체의 초기화
사용자 데이터 요청 -> Proxy가 확인 -> Proxy는 가짜라서 값이 없음 -> 영속성 컨텍스트에 초기화 요청 -> 영속성 컨텍스트는 DB를 조회 -> 영속성 컨텍스트가 실제 Entity 생성 -> 사용자가 요청한 데이터 표출
지연로딩 과 즉시로딩
지연로딩 : 프록시를 사용하여 실제로 객체가 사용될 때 SQL
즉시로딩 : 애초부터 SQL를 실행하여 데이터 가져옴
프록시와 즉시로딩
실무에서는 즉시로딩 사용 X (가급적 지연 로딩)
JPQL에서 N+1 문제를 일으킴
@ManyToOne, @OneToOne은 기본이 즉시로딩 -> LAZY로 변경필요
무조건 지연 로딩만 쓰세요