프록시와 연관관계 관리(난이도 상)
멤버와 팀과의 관계에서 연관관계가 맺어져 있지만
어떤 경우에는 멤버의 정보와 팀정보를 다 가져오고 다른 경우에는 팀정보가 아닌 멤버의 정보만 가져오고 싶을때
어떻게 해야할까???
// 멤버와 팀을 모두 가져오는 경우
public void printUserAndTeam(String memberId) {
Member member = em.find(Member.class, memberId);
Team team = member.getTeam();
System.out.println("회원 이름: " + member.getUsername());
System.out.println("소속팀: " + team.getName());
}
// 멤버만 가져오는 경우
public void printUser(String memberId) {
Member member = em.find(Member.class, memberId);
Team team = member.getTeam();
System.out.println("회원 이름: " + member.getUsername());
}
JPA입장에서는 다 땡겨온다고 가정했을 때 멤버만 가져올때도 다 땡겨오니까 낭비가 되버린다!!!
프록시 기초
em.find() vs em.getReference()
em.find() : 데이터베이스를 통해서 실제 엔티티 조회 / 진짜 객체를 줌
→ em.find는 이미 persist를 통해 디비에 들어가있는 데이터들을 select해서 가져올 수 있다.
em.getReference() : 데이터베이스 조회를 미루는 가짜(프록시) 엔티티 객체 조회 / 가짜 객체를 줌
→ getReference는 호출하는 시점에는 데이터베이스에 쿼리를 던져주지 않는다.
→ 이 객체가 실제로 사용(실행)되는 시점에서야 select해서 가져온다.
프록시 특징
실제 클래스를 상속받아서 만들어짐 그렇기때문에 실제 클래스와 겉 모양이 같다.
사용하는 입장에서는 진짜인지 가짜인지 구분할 필요없이 사용하면 된다. (이론상)
- 프록시라는 텅텅빈 가짜 테이블에는 getId(), getName()를 들고 있고 실제 엔티티를 상속하는 형태이다.
- 프록시 안에는 텅텅빈 상태인데 이 안에는 실제 객체의 참조 target을 들고 있다.
- 프록시 객체를 호출하면 프록시 객체는 참조하는 객체를 조회한다.
프록시 객체는 처음 사용할 때 딱 한번만 초기화
프록시 객체를 초기화 할 때, 프록시 객체가 실제 엔티티로 바뀌는게 아님 초기화 되면 프록시 객체를 통해서 실제 엔티티에 접근이 가능하다 라는 뜻
프록시 객체는 원본 엔티티를 상속받음, 따라서 타입 체크시에 주의해야함
( == 연산자로 타입을 비교하면 false / instance of 사용해서 타입비교는 정확하게 해줘야함) → 타입 비교는 정확성을 요구하기 때문에
영속성 컨텍스트에 찾는 엔티티가 이미 있으면 em.getReference()를 호출해도 실제 엔티티를 반환
프록시 객체의 초기화
Member member = em.getReference(Member.class, “id1”);
// 이과정까지는 쿼리상으로 아무런 동작이 없다.
member.getName();
// 실제로 getName()해서 뭔가 액션을 취해줬을때 프록시가 작동한다.
영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태일때, 프록시를 초기화하는 문제 발생
(하이버네이트에서는 org.hibernate.LazyInitializationException 발생시킴)
→ 프록시는 영속성 컨텍스트의 도움을 받아 의존해서 작동하는 것이기 때문에 에러 발생
프록시 확인하는 메서드
프록시 인스턴스의 초기화 여부 확인
PersistenceUnitUtil.isLoaded(Object entity)
프록시 클래스 확인 방법
entity.getClass().getName() 출력 (..javasist.. or HibernateProxy…)
프록시 강제 초기화
org.hibernate.Hibernate.initialize(entity); → 이거는 하이버네이트가 제공하는 것
참고 : JPA 표준은 강제 초기화 없음
강제 호출 : member.getName()
'Dev > JPA' 카테고리의 다른 글
RS) SQL 중심적인 개발의 문제점 (0) | 2022.02.01 |
---|---|
JPA의 사용 (0) | 2021.04.09 |
JPA 상속관계 매핑 (0) | 2020.07.30 |
다양한 연관관계 매핑 (0) | 2020.07.28 |
연관관계 매핑 기초 (0) | 2020.07.15 |