23.03.02 프록시

Kuno17·2023년 3월 2일
0

TIL/WIL

목록 보기
21/38
post-thumbnail

프록시?

em.find() vs em.getReference()
1. em.find() 데이터베이스를 통해서 실제 엔티티 객체 조회
2. em.getReference() 데이터베이스 조회를 미루는 가짜(프록시)엔티티 객체 조회 (쿼리 안나감)

프록시 특징

  1. 실제 클래스를 상속받아서 만들어진다.
  2. 실제 클래스와 겉 모양이 같다.
  3. 사용하는 입장에서는 진짜 객체인지 프록시 객체인지 구분하지않고 사용하면 됨.
  4. 프록시 객체는 실제 객체의 참조(target)를 보관
  5. 프록시 객체를 호출하면 프록시 객체는 실제 객체의 메소드 호출.

프록시 특징

  1. 프록시 객체는 처음 사용할 때 한 번만 초기화
  2. 프록시 객체를 초기화 할 때,프록시 객체가 실제 엔티티로 바뀌는 것은 아님, 초기화되면 프록시 객체를 통해서 실제 인티티에 접근가능
  3. 프록시 객체는 원본 엔티티를 상속받음, 따라서 타입 체크시 주의해야함 (== 비교 실패, 대신 instace of사용)
Member m1 =. em.find(Member.colss, member1.grtId());
Member m2 =. em.getReference(Member.colss, member2.grtId());

System.out.println("m1 == m2 : "+ (m1 == m2)); --> false
System.out.println("m1 == m2 : "+ (m1 instanceof Member)) --> true
System.out.println("m1 == m2 : "+ (m2 instanceof Member)) --> true
  1. 영속성 컨텍스트에 찾는 엔티티가 이미 있으면 em.getReference()를 호출해도 실제 엔티티 반환
Member member1 = new Member();
member1.setUsername("member1");
em.persist(member1);

em.flush();
emn.clera();

Member m1 =. em.find(Member.colss, member1.grtId());
System.out.println("m1  = "+ m1.getClass());
//영속성 컨텍스트에 올라가있다. 이 상태에서

Member refer = em.getReference(Member.class, member1.getId());
System.out.println("refer = " + refer.getClss());

//결과는 다음과 같이 나온다.
m1 = class hellojpa.Member
refer = class hellojpa.Member

!! 왜 refer역시 Member가 나오는걸까? (프록시가 아닌)
JPA는 하나의 Transaction안에서의 같은것에 대한 보장을 해준다.
프록시에서 가져오더라도 JPA에서는 == 비교시 true보장해주는 속성이 있다. 이미 영속성 컨텍스트에 존제하는경우는 다음과같은 결과를 만든다.

  1. 영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태일 때, 프록시를 초기화하면 문제 발생.
Member member1 = new Member();
member1.setUsername("member1");
em.persist(member1);

em.flush();
emn.clera();

Member refMember = em.getReference(Member.class, member1.getId());
System.out.println("refMember = " + refMember.getClass()): //Proxy

em.detach(refMember); // 만약에 영속성 컨텍스트에서 꺼낸다면?
em.clear(); // 영속성 컨텍스트를 다 비워버린다면?

refMember.getUsername(); // 프록시를 초기화 할 수 없게된다.

프록시 확인

  1. 프록시 인스턴스의 초기화 여부 확인
    PersistenceUnitUtil.isLoaded(Object entity) 엔티티 매니저 펙토리에서 얻을 수 있다.
emf.PersistenceUnitUtil().isLoaded()
  1. 프록시 클래스 확인 방법
    entity.getClss().getName() 출력
System.out.println(refMember = " + refMember.getClss().getName())
  1. 프록시 강제 초기화
    org.hibernate.Hibernate.initialize(entity);
Hibernate.initialize(refMember);

프록시를 이해해야 즉시로딩과 지연로딩에 대한 이해를 할 수 있기 떄문에 이해가 필요하다.

profile
자바 스터디 정리 - 하단 홈 버튼 참조.

0개의 댓글