-
-
안녕하세요? 오늘은, JPA의 연관관계 관리 중, 프록시( proxy )에 대해서 알아보도록 하겠습니다.
프록시란?
: JPA에서는 불필요한 쿼리를 최적화하기 위해서는, 지연로딩과 프록시라는 개념으로 해결
※ 지연로딩은, 다음 포스팅에 다뤄보도록 하겠습니다.
※ 해당 포스팅은, 즉시로딩과 지연로딩의 매커니즘의 이해를 돕기위한, 개념 지원 포스팅 입니다.
* find()
: DB를 통해서 실제 엔티티를 바로 조회
* getReference()
: DB 조회를 미루는 가짜(프록시) 엔티티 객체 조회
+
getReference() 가 실행 되었을 때, 프록시 객체는 실제 객체의 참조(target)을 보관한다.
프록시 객체를 호출 시, 프록시 객체는 실제 객체의 메소드를 호출하게 된다.
샘플소스)
EntityManagerFactory emf = Persistence.createEntityManagerFactory("유닛명");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
EntityA entityA1 = new EntityA();
entityA1.setName("entityA1_1");
em.persist(entityA1);
EntityA entityA2 = new EntityA();
entityA2.setName("entityA2_1");
em.persist(entityA2);
EntityA entityA3 = new EntityA();
entityA3.setName("entityA3_1");
em.persist(entityA3);
em.flush();
em.clear();
// 엔티티 객체 비교
EntityA findEntityA1 = em.find(EntityA.class, entityA1.getId());
EntityA findEntityA2 = em.find(EntityA.class, entityA2.getId());
System.out.println("findEntityA1 == findEntityA2 : "
+ (findEntityA1.getClass() == findEntityA2.getClass()));
// 프록시 객체 비교
EntityA findEntityA3 = em.getReference(EntityA.class, entityA3.getId());
System.out.println("findEntityA1 == findEntityA3 : "
+ (findEntityA1.getClass() instanceof findEntityA3.getClass()));
// 영속성 컨텍스트에 엔티티가 존재 시, 프록시 객체가 아닌, 실제 엔티티 반환
EntityA findEntityA4 = em.getReference(EntityA.class, entityA2.getId());
System.out.println("findEntityA2 == findEntityA4 : "
+ (findEntityA2.getClass() == findEntityA4.getClass()));
tx.commit();
+
: 프록시 객체는 처음 사용할 때 한번만 초기화 ★★★
: 프록시 객체를 초기화 할 때, 프록시 객체가 실제 엔티티로 바뀌는 게 아님
> 초기화 되면, 프록시 객체를 통해서 실제 엔티티에 접근 가능
: 프록시 객체는 원본 엔티티를 상속받음
> 타입 체크 시 주의 필요 (== 비교 대신, instance of 사용)
: 영속성 컨텍스트에 찾는 엔티티가 이미 있다면, getReference를 호출해도 실제 엔티티를 반환
: 영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태(detach/colse)일 때, 프록시 초기화 시 문제 발생
> LazyInitializationException 발생
※ 보통 실무에서는, 트랜잭션이나 영속성 컨텍스트를 끝내고, 프록시를 조회 시, 해당 내용을 자주 만나게 될 것이다.
프록시 확인 방법
: 프록시 인스턴스의 초기화 여부 확인
> emf.PersistenceUnitUtil.isLoaded(엔티티)
: 프록시 클래스 확인 방법
> 엔티티.getClass().getName()
: 프록시 강제 초기화
> Hibernate.initialize(엔티티)
※ JPA 표준에서는, 강제 초기화란 없다.
: 강제호출
> 엔티티.get속성명()
-
오늘은, JPA의 연관관계 관리 중, 프록시에 대해서 알아보았습니다.
그럼 오늘도 즐거운 하루 되시길 바라겠습니다.
'프로그래밍 > Back-end' 카테고리의 다른 글
JPA JPQL 타입 표현식과 기타식 그리고 조건식과 기본 함수 (0) | 2024.10.18 |
---|---|
JPA 쿼리 JPQL 페이징 조인 서브쿼리 (0) | 2024.10.18 |
JPA QueryDSL 네이티브SQL JDBC MyBatis (0) | 2024.10.18 |
JPA 지연로딩 즉시로딩 (0) | 2024.10.17 |
JPA 영속성 전이 CASCADE 고아 객체 (0) | 2024.10.15 |
JPA 영속성 영속상태와 준영속상태 (0) | 2024.10.15 |
JPA 영속성 Flush (0) | 2024.10.15 |
JPA 영속성 컨텍스트의 장점에 대하여! (0) | 2024.10.15 |