JPA(프록시, lazy loading)

오민석·2021년 5월 19일
0

프록시

  • em.find(): 실제 entity 조회
  • em.getReference(): 가짜(프록시) entity 객체 조회

    em.getReference는 실제로 DB가 실행되지 않고 가짜객체를 가져오는데, getReference를 호출하여 얻어낸 데이터를 어디선가 사용하는 순간 이 값을 채우기 위해 DB에 쿼리를 날려서 진짜 객체를 가져온다

  1. 실제 entity를 상속받아 겉 모습은 같다.

  2. 프록시 객체는 target이라는 실제 객체 참조를 보관하는데 처음에는 null 값이다.

  3. 그러면 JPA가 영속성 컨텍스트에 진짜 객체를 가져오라고 요청한다.
    이에 따라 영속성 컨텍스트는 진짜 객체를 DB에서 조회해서 실제 엔티티 객체를 생성한다.

  4. 그리고 그걸 프록시 객체의 target에 연결해 준다.

  5. 그래서 getName을 하면 target의 진짜 객체에 대해 getName을 해 준다.

  6. 이후에 같은 메소드를 호출하면 쿼리문 없이 프록시 객체로부터 바로 값을 가져온다.

Lazy Loading(지연로딩)

@ManyToOne(fetch = FetchType.LAZY)
@ManyToOne(fetch = FetchType.EAGER)
이렇게 2가지 의 방식이 있는데 EAGER 방식을 사용하게 되면 N+1 쿼리 문제와 불필요하게 모든 칼럼은 JOIN하게 되서 비효율적이다. 물론 효율적일 때 도 있다.

하지만 지연 로딩을 하게 되면 필요할 때만 필요한 값을 가져온다. 하지만 이 또한 N+1 문제가 있어 FETCH로 해결해야 한다.

List<Album> albums = albumRepository.findAll(); // (1) N+1 발생하지 않음
for (Album album : albums) {
    System.out.println(album.getSongs().size()); // (2) Song에 접근 N+1 발생.
}

0개의 댓글