작성
·
4K
답변 4
35
2020. 06. 27. 21:56
안녕하세요. mingi.kang님^^
우선 즉시 로딩과 fetch 조인은 다른 기능입니다.
em.find() 등을 통해서 엔티티 하나만 조회할 때는 즉시 로딩으로 설정하면 연관된 팀도 한 쿼리로 가져오도록 최적화 되지만 JPQL을 사용하면 이야기가 달라집니다. JPQL은 연관관계를 즉시로딩으로 설정하는 것과 상관없이 JPQL 자체만으로 SQL로 그대로 번역됩니다.
예시로 설명해드릴께요.
즉시 로딩(EARGR로 설정)
1. 멤버 전체를 조회하기 위해 JPQL 실행 select m from member m
2. JPQL은 EAGER와 무관하게 SQL로 그대로 번역 -> select m.* from member
3. JPQL 결과가 member만 조회하고, team은 조회하지 않음
4. member와 team이 즉시 로딩으로 설정되어 있기 때문에 연관된 팀을 각각 쿼리를 날려서 추가 조회 (N+1)
지연 로딩(LAZY로 설정)
1. 멤버 전체를 조회하기 위해 JPQL 실행 select m from member m
2. JPQL은 EAGER와 무관하게 SQL로 그대로 번역 -> select m.* from member
3. JPQL 결과가 member만 조회하고, team은 조회하지 않음
4. member와 team이 지연 로딩으로 설정되어 있기 때문에 가짜 프록시 객체를 넣어두고, 실제 회원은 팀은 조회하지 않음
5. 실제 team을 사용하는 시점에 쿼리를 날려서 각각 조회(N+1)
fetch join 또는 엔티티 그래프(EAGER, LAZY 상관 없음)
1. 멤버와 팀을 한번에 조회하기 위해 JPQL+fetch join 실행 select m from member m join fetch m.team
2. JPQL에서 fetch join을 사용했으므로 SQL은 멤버와 팀을 한 쿼리로 조회 -> select m.*, t.* from member join team ...
3. JPQL 결과가 member와 team을 한꺼번에 조회함
4. member와 team이 fetch join으로 한번에 조회되었으므로 N+1 문제가 발생하지 않음
추가로 다음 내용도 보시면 도움이 되실꺼에요. https://www.inflearn.com/questions/30446
도움이 되셨길 바라며 감사합니다^^
9
2020. 06. 28. 23:40
네 맞습니다^^
조금 더 보충을 해드리자면 JPA에서 모든 연관관계는 꼭! LAZY로 설정하시길 바랍니다. 실무에서 EAGER는 그냥 없다고 생각하시는 것이 더 좋습니다. 그렇게 해야 member만 필요해서 조회할 때, member만 조회가 됩니다.
그런데 때때로 특정 기능에서는 member와 team이 함께 필요한 경우가 있습니다. 이때 그 상황에 맞는 로직에서 fetch join을 사용하면 n+1 문제를 해결할 수 있습니다.
1
1
2020. 06. 28. 11:52
그럼 fetch join은 jpa에서 jpql을 사용하여 데이터를 가져올 때 발생하는 N+1문제를 해결하기 위함이라고 생각해도 될까요..?
2022. 08. 28. 00:29
오랜만에 강의를 들어도 이러한 영한님 열정을 다시 한번 느낄 수 있어서 좋네요..ㅎㅎ
감사합니다!