- 지연 로딩을 통해 연관관계 데이터를 실제 조회 시점에 가져오는 것이 가능하다.
fetch = FetchType.LAZY
@ManyToOne(fetch = FetchType.LAZY) // 지연 로딩으로 세팅
@JoinColumn(name = "TEAM_ID")
private Team team;
- 연관 관계 엔티티를 지연 로딩으로 세팅하면 프록시로 가져온다.
- 지연 로딩으로 가져온 엔티티는 실제 값을 사용하는 시점에 프록시를 초기화한다.
Member member1 = new Member();
member1.setUsername("zayson1");
member1.setTeam(team);
// Team의 데이터는 프록시로 가져온다. (Team 조회 쿼리 안날아감)
Member member = em.find(Member.class, member1.getId());
// 실제 Team을 사용하는 시점에 프록시를 초기화한다. (Team 조회 쿼리 날아감)
System.out.println("member.getTeam().getName() = " + member.getTeam().getName());
- 연관관계를 함께 조회하는 경우가 많은 경우는 즉시 로딩을 사용할 수 있다.
fetch = FetchType.EAGER
- 즉시 로딩으로 설정한 연관 관계 엔티티는 조인이되어 한번에 조회가 된다.
- 한번에 데이터를 조회해 오기 때문에 프록시 객체로 연관 관계를 가져올 필요가 없다. 따라서, 즉시 로딩된 연관관계 엔티티는 실제 클래스 타입이다.
🚨 실무에서는 즉시 로딩을 사용을 지양한다.
✔️ 즉시 로딩을 이용하는 경우 예상하지 못한 SQL이 발생할 수 있다.
- 즉시 로딩이 된 테이블이 1-2개면 체감이 안되지만, 실무에서는 테이블이 여러개이고 여러개가 즉시로딩 되어있다면 여러개의 테이블을 모두 조인해서 가져온다!!
✔️ 즉시 로딩은 JPQL에서 N+1 문제를 발생시킨다.
- 회원 데이터가 10개인 경우 연관관계인 Team 데이터를 조회하기 위해 10번의 쿼리가 추가적으로 발생한다.
- 회원 데이터 조회 쿼리 (1) + 회원 10명에 대한 Team 정보 조회 (10) = N + 1 문제
SELECT * FROM MEMBER; // 1번 -> 결과 : 10 row
SELECT * FROM TEAM WHERE MEMBER_ID = (1-10); // 10번의 쿼리 발생
💡 N + 1 문제 해결법
- 모든 연관 관계는 지연 로딩을 기본으로 한다.
- Fetch Join이나 엔티티 그래프 기능을 이용해 데이터를 조회한다.
- BatchSize를 지정한다.
✔️ @XtoOne 관계는 default가 즉시 로딩이기 때문에 지연 로딩으로 변경한다.
📄 References
김영한님의 자바 ORM 표준 JPA 프로그래밍 - 기본편 : https://www.inflearn.com/course/ORM-JPA-Basic/dashboard
반응형
'Backend > JPA' 카테고리의 다른 글
값 타입 (0) | 2022.07.26 |
---|---|
영속성 전이 (Cascade), 고아 객체 (0) | 2022.07.21 |
프록시 (0) | 2022.07.20 |
상속관계 매핑 (0) | 2022.07.20 |
엔티티 설계의 주의사항 간단 정리 (0) | 2022.07.05 |