JPA

[JPA] 지연로딩

행복하개! 2020. 10. 22. 03:46

 

 

참조가 있는 엔티티를 조회할때는 그 참조를 한번에 같이 즉시 조회할지 아니면 사용할때 조회할지에 대한 정의를 내려줘야한다. 

 

즉시 로딩은 엔티티 객체 조회시에 한번에 다 가져오는 것이고,

지연 로딩은 참조의 메서드를 호출 했을 때, 초기화했을 때 그때 불러오는 것이다.

 

@ManyToOne과 @OneToMany의 fetch 전략은 기본이 즉시로딩이다. 이것을 지연로딩으로 바꾸려면 아래 코드와 같다.

@Entity
public class Member extends BaseEntity {

    @Id
    @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "USERNAME")
    private String username;

    @ManyToOne(fetch = FetchType.LAZY) // EAGER은 즉시 가져오는 것
    @JoinColumn
    private Team team;
}

즉시로딩은 LAZY 대신에 EAGER을 사용하면 된다.

 

 

 

근데 즉시로딩은 가능하면 사용하면 안된다. 지연 로딩 위주로 사용해야 하는데, 즉시 로딩을 사용하게 되면 정말 예상하지 못하는 어마어마한 SQL 쿼리가 나갈 수 있다.

예를 들어 참조의 참조가 연쇄적으로 되어있는 엔티티가 있다고 가정하면, 심지어 1만개의 엔티티가 존재하면 그 모든걸 다 조회하는 쿼리가 날라가는 것이다. 이것은 성능상에서 큰 문제가 된다.

 

또한 JPQL에서 N+1 문제가 발생한다. 일반적으로 사용하는 em.find()는 JPA알아서 최적화를 다해줘서 1번만 쿼리가 나가는데 JPQL은 SQL문으로 변환되어서 쏘는 쿼리이다. 문제는 쌩 SQL을 날리는 거라 최적화가 안되기 때문에 어떤 엔티티를 조회하고 나면 뒤늦게 최적화를 하느라 나머지 참조를 불러오면서 쿼리가 또 나간다.. 

 

무조건 지연로딩으로 다 셋팅하고 즉시 로딩이 필요한 부분의 경우에는 JPQL의 fetch를 쓴다.

 

 

 

명심!

실무에스는 무조건 지연 로딩!

즉시 로딩이 필요하면 JPQL fetch 조인, 엔티티 그래프 기능을 사용.

'JPA' 카테고리의 다른 글

[JPA] orphanRemoval  (0) 2020.10.22
[JPA] CASCADE  (0) 2020.10.22
[JPA] 프록시  (0) 2020.10.22
[JPA] @MappedSuperclass  (0) 2020.10.20
[JPA] 상속관계 매핑  (0) 2020.10.20