1. 프록시
- em.find() vs em.getReference()
- em.find() : 데이터베이스를 통해 실제 엔티티 객체를 조회
- em.getReference() : 데이터베이스 조회를 미루는 가짜(프록시) 엔티티 객체를 조회
프록시 초기화
- 실제 클래스를 상속 받아서 만들어짐
- 겉 모양이 같음
- 실제 객체의 참조를 보관
- 요청 -> 초기화 확인 -> 영속성 컨텍스트 통해 DB 조회 -> 실제 엔티티 생성 -> 프록시 연결
특징
- 객체는 처음 사용할 때 한번만 초기화
- 초기화시 프록시 객체가 실제 엔티티로 바뀌는 것이 아니라 참조하여 실제 엔티티에 접근
- 실제 인티티를 상속 받으므로 (== 비교 실패, instance of 사용)
- 영속성컨텍스트에 찾는 엔티티가 있으면 em.gerRefence()를 호출해도 실제 엔티티 반환 : 한 트랜잭션 안에서는 동일성을 보장하는 JPA의 특성
- 준영속 상태일 때는 조회가 되지 않고 예외가 발생
확인
//프록시 초기화 확인
User infoProxy = em.getReference(User.class, user1.getId());
System.out.println("emf.getPersistenceUnitUtil().isLoaded(infoProxy) = "
+ emf.getPersistenceUnitUtil().isLoaded(infoProxy));
//클래스 확인
System.out.println("infoProxy.getClass() = " + infoProxy.getClass().getName());
//프록시 강제 초기화
Hibernate.initialize(infoProxy);
//JPA 표준은 강제 초기화 없음
2. 즉시로딩 과 지연로딩
지연로딩
- 연관관계가 맺어진 객체끼리 서로 참조가 낮을 때
- lazy를 통해 프록시로 조회 -> 지연 로딩
즉시로딩
- 연관관계가 맺어진 객체끼리 참조가 높을 때, 호출시에 join을 통해 다 가지고 옴
- eager를 통해 실제 엔티티로 조회 -> 즉시로딩
- 실무에서 비추천, 예상치 못한 SQL 발생, JPQL에서 N+1문제를 발생
- ManyToOne, OneToOne 어노테이션 default값은 즉시로딩이기 때문에 Lazy로 설정
** N+1 문제 : jpql 에서 연관관계가 있는 테이블에 대해 추가로 sql을 날림
** lazy로 사용하고 join fetch나 엔티티 그래프 기능을 사용하여 해결