[JPA] 프록시와 즉시로딩 그리고 지연로딩

시나브로·2021년 5월 25일
0

JPA

목록 보기
9/12
post-thumbnail

1. 프록시


  연관관계가 존재하는 엔티티는 조회할 때마다 값을 모두 들고 와야할까?
필요 값들에 대해서만 값을 조회한 뒤, 연관된 엔티티를 사용하려 할 때, 다시 값을 조회한다면 충분히 효율적일 것이다. 이같은 방법을 JPA에서는 지연로딩이라 칭한다.
이 지연로딩을 사용하기 위해, 사용하기 전까지 연관된 엔티티 객체를 채워넣는 가각체를 프록시라 한다.


1.1 특징

 프록시 객체는 참조 대상의 실제 클래스를 상속받아 만들어진다. 이 프록시 객체로 엔티티를 채워넣은 후, 사용자가 엔티티 객체를 사용하려할 때, DB를 조회한 뒤 실제 엔티티 객체를 생성한다. 이를, 프록시 객체의 초기화라 한다.
전반적인 흐름은 아래와 같다

  1. 사용자가 연관된 엔티티를 호출한다
  2. 프록시 객체는 영속성 컨텍스트에 엔티티 생성 요청한다(초기화 작업)
  3. 영속성 컨텍스트는 DB를 조회해 실제 엔티티 객체를 생성한다
  4. 프록시 객체는 전달받은 실제 엔티티 객체를 담는다(target)
  5. 프록시 객체는 실제 엔티티 객체(target)의 값을 호출해 결과를 전달한다.
  • 특징
    • 프록시 객체는 한번만 초기화된다
    • 프록시 객체는 실제 엔티티 클래스를 상속받은 객체다
    • 영속성 컨텍스트에 이미 엔티티가 있으면, em.getReference()를 호출해도 프록시가 아닌 실제 엔티티를 전달한다
    • 준영속 상태에서는 영속성 컨텍스트와 연결이 되지 않아 에러가 발생한다

1.2 식별자

 프록시는 조회할 때 전달한 pk를 보관하고 있는데, 이때문에 pk를 조회하는 과정에서는 엔티티 접근 방식에 따라 프록시 초기화가 일어나지 않는다.

  • @Access(AccessType.PROPERTY) : 초기회 일어나지 않음
  • @Access(AccessType.FILED) : getId가 어떤 필드만 조회하는지 알 수 없어 초기화 발생

1.3 프록시 여부 확인

 프록시 인스턴스가 초기화되었는지 여부를 확인하는 메소드를 제공한다.

ex)


boolean isLoad = em.getEntityManagerFactory()
  		    .getPersistenceUnitUtil().isLoaded(entity);
...


2. 즉시 로딩과 지연 로딩


  프록시를 사용하여 어떻게 연관된 엔티티에 대해 필요할 때, 초기화를 할 수 있는지 알아보았다. 이제 이를 활용한 즉시 로딩과 지연 로딩을 살펴본다.

  • 즉시 로딩 : 엔티티를 조회할 때 연관된 엔티티 모두 조회
  • 지연 로딩 : 연관된 엔티티를 실제 사용할 때 조회

2.1 즉시 로딩

@nTon의 속성에서 fetch value값을 EAGER로 설정해준다.

@Entity
public class member{

...
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "TEAM_ID")
    private Team team;
    ...

}

  외래 키에서 null 허용이 적용된다면, 데이터 조회를 위해 outer join을 사용하게 된다. 성능상의 이슈를 해결하기 위해 inner join을 사용하고 싶다면 not null 제약조건을 걸어두자


2.2 지연 로딩

@nTon의 속성에서 fetch value값을 Lazy로 설정해준다.

@Entity
public class member{

...
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "TEAM_ID")
    private Team team;
    ...

}



3. CASCADE


  특정 엔티티를 영속 상태로 만들 때, 연관 엔티티도 동기화하기 위해 사용한다. 즉, 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장한다

@Entity
public class Parent{

...
    @OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)
    private List<Child> children = new ArrayList<Child>();
    ...

}


4. 고아 객체


  부모 엔티티와 연관관계가 끊어진 객체를 고아 객체라 하는데, 이를 자동으로 제거하는 기능을 고아 객체 제거라 한다. 부모 엔티티에서 자식 엔티티 연관관계를 끊었을 때, 자동으로 제거되는 설정을 알아본다.

@Entity
public class Parent{

...
    @OneToMany(mappedBy = "parent", orphanRemoval = true)
    private List<Child> children = new ArrayList<Child>();
    ...

}












참고 도서

profile
Be More!

0개의 댓글