반응형
1. 프록시가 필요한 이유
- 엔티티를 조회할 때 연관관계를 맺고 있는 다른 엔티티도 같이 조회한다.
- 연관된 엔티티가 항상 필요하지 않을 수도 있기 때문에 불필요한 데이터 조회가 발생하게 된다.
그렇기에 실제 사용하는 시점에 데이터베이스를 조회할 수 있게 해야하는데 이 때 프록시를 사용하면 된다. - 실제 사용될 때까지 DB 조회를 지연시킬 수 있도록 실제 엔티티 대신할 가짜 객체가 필요한데 이를 프록시 객체라고 한다.
2. 프록시 객체
- JPA에서 식별자로 엔티티를 조회할 때 'EntityManager.find()'를 사용한다. 이 메소드는 영속성 컨텍스트 내 1차캐시에 엔티티가 없을 경우 DB 조회하여 저장하게 된다.
- 만약 엔티티를 실제 사용하는 시점까지 DB조회를 지연시키고 싶으면 EntityManger.getReference()를 사용하여 프록시 객체를 얻을 수 있다.
- getReference()는 DB 접근을 위임한 프록시 객체를 반환하는데 프록시 클랙스는 실제 클래스를 상속받아 만들어져 실제 클래스와 모양이 동일한다. 그렇기에 사용자는 별도 구분 없이 그대로 사용하면 된다.
프록시 객체를 호출하면 프록시 객체는 실제 객체의 target 정보를 보관하고 있기에 실제 객체의 메소드가 호출된다.
3. 프록시 객체의 초기화
- 프록시 객체가 실제 사용될 때 DB에서 데이터를 조회하여 실제 엔티티 객체가 생성되는 것을 의미한다.
- 프록시 초기화 과정
- order.getDelivery()을 호출
- 프록시 객체에는 실제 엔티티를 참조하는 변수(target)이 있지만 영속성 컨텍스트에는 해당 엔티티가 없습니다.
getDelivery() 메소드를 실행하기 위해서는 엔티티 정보가 필요하므로 영속성 컨텍스트에 실제 엔티티를 생성 요청합니다.
(초기화 단계) - 영속성 컨텍스트는 DB를 조회합니다.
- 조회 이 후 영속성 컨텍스트는 실제 엔티티 객체를 생성하여 '1차캐시'에 보관합니다.
- 프록시 객체는 생성된 실제 엔티티 객체의 참조를 targe 변수에 보관하고, 실제 엔티티 객체의 getDelivery()를 호출하여 결과를 반환합니다.
- 프록시 초기화 특징
- 프록시 객체는 처음 사용할 때 한번만 초기화된다.
- 프록시 격체를 초기화한다고 프록시 객체가 실제 엔티티로 바뀌는 것이 아닌 프록시 객체를 통해 실제 엔티티에 접근할 수 있다.
- 프록시 객체는 상속받은 객체이므로 타입 비교는 'instanceof'를 사용하고, 필드값은 getter()를 통해 가져와야한다.
- 영속성 컨텍스트에 엔티티가 있는 경우 EntityManger.getReference()를 호출해도 프록시가 아닌 실제 엔티티를 반환한다.
- 준영속 상태는 영속성 컨텍스트의 관리를 더 이상 받지 않는 상태이므로 준영속 상태에서 프록시를 초기화하면 org.hibernate.LazyInitializationException 이 발생한다.
4. 프록시 식별자
- 엔티티를 프록시로 조회할 때 식별자(PK값)를 이용하여 파라미터로 전달한다. 프록시 객체는 이 식별자 값을 보관한다.
만약 다음과 같은 Member Entity에서 pk는 id가 된다.
위와 같이 프록시 조회 시 getId()의 경우 내부에 식별자, 즉 pk 값이 어떤것인지 알고 있다. 그렇기에 해당 경우에는 프록시를 초기화하지 않는다. getName()의 경우 식별자 값이 아니기에 프록시 초기화 처리를 한다. - 엔티티 접근방식에 따른 프록시 초기화 전략
- @Access(AccessType.PROPERTY) : 초기화 되지 않음.
- @Access(AccessType.FIELD) : 초기화 처리를 한다. JPA가 getId()메소드가 id만 조회하는 메소드인지 다른 필드까지 활용하여 다른 작업을 하는 메소드인지 알지 못하기 때문이다.
5. 프록시 확인
- 프록시 인스턴스의 초기화 여부 : EntityManagerFactory.PersistenceUnitUtil.isLoaded(Object entity)
- 프록시 클래스 확인 : entity.getClass().getName()
- 프록시 강제 초기화 : org.hibernate.Hibernate.initialize(entity
반응형
'Backend > Spring' 카테고리의 다른 글
[JPA] N+1 문제 (0) | 2022.02.28 |
---|---|
JPA 즉시로딩(Eager Loading)과 지연로딩(Lazy Loading)? (0) | 2022.02.24 |
영속성 컨텍스트란? (0) | 2022.02.22 |
Spring Data JPA 란? (0) | 2022.02.20 |
IOC(Inversion of Colntrol) 컨테이너 (0) | 2017.06.27 |