이 글은 김영한님의 JPA 강의 중 8장 프록시와 연관관계 관리를 듣고 정리한 내용입니다 :)
강의 : 자바 ORM 표준 JPA 프로그래밍 - 기본편
교재 : 자바 ORM 표준 JPA 프로그래밍🤷♀️
엔티티 조회는 2가지 방식으로 할 수 있는데,
이때, 2번 getReference 방법을 사용하면 가짜 엔티티 객체를 조회하게 되는데,
이때 이 가짜 엔티티를 프록시라 한다! 이 프록시에 대해서 알아보자-!
프록시 객체의 초기화 과정은 아래와 같다!
여기서 주의! 타입 비교할때, ==으로 비교하면 안 되고 instance of를 사용한다.
참고로 영속성 컨텍스트에 있으면 == 으로 했을 때 같은 값, 즉 동일성을 보장함 ⇒ JPA의 특징
em.detached(); 혹은 em.closed(); 으로 준영속 상태를 만들수 있음
em.clear()하면 영속성 컨텍스트를 꺼버림
둘다 프록시 객체를 초기화 못하고 에러 발생!
⇒ 아예 어노테이션으로 준영속상태 안되게끔 ⇒ 추가
Member refMember = em.getReference(Member.class, member1.getId()); //Proxy
// 프록시가 실제 사용된적이 없기에 초기화 안되었음
em.getPersistenceUnitUtil().isLoaded(); // false
Member refMember = em.getReference(Member.class, member1.getId()); //Proxy
// 프록시가 실제 사용된적이 없기에 초기화 안되었음
refMember.getClass();
Member refMember = em.getReference(Member.class, member1.getId()); //Proxy
Hibernate.initialize(refMember); //강제 초기화
참고로 이 강제초기화 방법은 하이버네이트의 방식이고, JPA 표준은 강제 초기화 방법이 따로 없다.
하이버네이트 말고는, 강제 호출은 member.getName()을 사용할 것.
지연 로딩 : 프록시 객체로 실제 엔티티 객체 참조
즉시 로딩 : 연관관계에 있는 객체까지 바로 조회
// 즉시 로딩 - 패치 타입 EAGER 설정
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "team_id")
private Team team;
// 지연 로딩 - 패치 타입 LAZY 설정
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id")
private Team team;
=> 이론적으로는 자주 함께 사용하는 연관관계끼리는 즉시 로딩, 아니면 지연로딩을 쓰지만,
실무에서는 그냥 다 지연 로딩을 사용하자!
특히 @ManyToOne, @OneToOne은 기본이 즉시 로딩이니까 → LAZY로 바꾸어야 함!