비즈니스 로직에서 연관관계가 걸려있을 때, 함께 조회하지 않게 하는 방법은
JPA의 지연로딩 LAZY를 사용해 프록시로 조회하는 방법으로 해결가능.
Entity 사이의 관계가 다대일 @ManyToOne 관계로 매핑되어있는 상황에서,
@ManyToOne 어노테이션에 fetch 타입을 줄 수 있다.
@ManyToOne(fetch = FetchType.LAZY)
지연로딩(LAZY)
엔티티 조회 시점이 아닌 엔티티 내 연관관계를 참조할 때 해당 연관관계에 대한 SQL이 질의되는 기능,
fetch = FetchType.LAZY 옵션으로 지정할 수 있다.
엔티티 조회 시, 연관관계 필드는 프록시 객체로 제공.
즉시로딩
엔티티 조회 시 연관관계에 있는 데이터까지 한번에 조회해오는 기능,
fetch = FetchType.EAGER 옵션으로 지정할 수 있다.
즉시로딩으로 조회된 엔티티의 연관관계 필드에는 실제 엔티티 객체가 반환.
주의사항
- 실무에서는 가급적 지연로딩 사용
- 즉시로딩 사용시 예상하지 못한 SQL 발생할 수 있음.
- 즉시로딩은 JPQL에서 N+1 문제를 일으킨다.
- 실무에서 복잡한 쿼리를 많이 풀어내기 위해 JPQL 많이 사용.
- em.find()는 PK를 정해놓고 DB에서 가져와 JPA 내부에서 최적화 할 수 있다.(한방쿼리)
- 하지만, JPQL에선 입력 받은 query string이 그대로 SQL로 변환된다.
- N+1의 문제의 의미는 쿼리를 1개 날렸는데, 그것 때문에 추가 쿼리가 N개 나간다는 의미.
- 실무에서 엔티티 중 함께 사용하는 경우 LAZY로 해놓고 계속 쿼리 두번 날려서 조회를 해야할까?
-> 이런 경우 JPQL의 fetch join을 통해 해당 시점에 한방 쿼리로 가져와 사용가능.
-> 추가로, 엔티티그래프와 어노테이션으로 푸는 방법, 배치 사이즈 설정으로 해결가능.
-> 대부분 fetch join으로 해결
연관관계 별 fetch 옵션 기본값
- @ManyToOne : EAGER
- @OneToOne : EAGER
- @ManyToMany : LAZY
- @OneToMany : LAZY