JPQL fetchJoin (실무에서 정말중요함)
엔티티에 fetchType-LAZY로 설정된 지연로딩 필드를 즉시로딩으로 가져오게 한다.
-SQL조인 종류가 아니다 JPA 전용으로 존재하는 명령어
-JPQL에서 성능 최적화를 위해 제공하는 기낭
-연관된 엔티티나 컬렉션을 SQL 한번에 함께 조회하는 기능
-join fetch 명령어 사용
-페치조인[left [outer]|[inner]] join fetch 조인경로
엔티티 페치 조인
-회원을 조회하면서 연관된 팀도 함께 조회(sql 한번에)
-sql을 보면 회원 뿐만 아니라 팀 (T.*)도 함께 select
(jpql)
select m from Member m join fetch m.team
(sql)
select m.* , t.* from Member M
Inner join team t on m.team_id = t.id
Member 조회시 team도 동적으로 조회하고 싶은경우 사용
그러면 select m 만 적었는데 sql에는 m과 t까지 나온걸 볼 수 있다.
(join fetch 로 엔티티속 객체 필드를 한번에 가져온다,)
쿼리로 내가 원하는 쿼리를 동적으로 가져 오는것
Join fetch 예
{Member}
id name Team_id
1 회원1 1
2 회원2 1
3 회원3 2
4 회원4 null
{Team}
id name
1 팀A
2 팀B
3 팀C
위 테이블 관계를 Inner Join 하면
Member join team
id name Team_id id name
1 회원1 1 1 팀A
2 회원2 1 1 팀A
3 회원3 2 2 팀B
위 표에 따르면
fetchJoin 된 위 상황과 같이 즉시 로딩처럼
필요한 엔티티가 모두 1채 캐시에 들어가게 된다. 쿼리는 1번만 실행되는게 핵심
Many to one fetch join
String query = "select m from Member m";
List<Member> members = em.createQuery(query, Member.class).getResultList()
위 쿼리로 값을 가져오면
일단 Team은 @ManyToOne이니 기본 지연로딩(fetch-LAZY)이다.
그래서 일단 Member값만 가져와 프록시에 넣어두고
실제 Tram을 조회하는 시점에서야 영속성 프록시에 team 객체가 들어가게 된다.
그래서 Join에 필요한 엔티티들도 프록시에 있으면 프록시에서 가져온다
만약 다대일 쿼리를 실행해서 값을 가져온다고 했을때
회원1(sql) , 팀A(sql)
회원2(sql) , 팀A(1차캐시)
회원3(sql) , 팀B(sql)
회원 1 , 2, 3은 각각 처음 조회하는 내용이기 때문에 1차캐시에 없는 내용이라 DB에서 조회하게 된다
팀 A 의 경우 처음 조회시엔 1차캐시에 없는 내용이기 때문에 DB에서 조회하게 된다
다시 팀 A를 조회할경우 1차캐시에 이미 있는 내용이기 때문에 SQL을 실행하지 않고 조회가 가능하다.
팀B의 경우 역시 처음 조회하는 경우라 1차캐시에 없어서 DB에서 조회한다.
이런 경우의 수가 무수히 많으면 쿼리를 그만큼 실행하게 되는데
이를 n+1 이라한다.
여기서 1은 최초의 조회쿼리이고 n은 그에 부가적인 지연로딩들을 의미한다.
이것을 해결하기 위해서 join fetch를 사용한다.
String query = "select m from Member m join fetch m.team"
member 조회시 team을 즉시로딩으로 가져온다.
그렇게 되면 모든 경우의 수에 필요한 엔티티가 쿼리한번으로 모두 불러와지게 된다.
fetchType-LAZY라도 join fetch의 즉시로딩이 우선된다,
'JPA' 카테고리의 다른 글
| 2월 16일 JPA JPQL 페치조인의 특징과 한계 (0) | 2023.02.16 |
|---|---|
| 2월 16일 JPA 일대다 관계, 컬렉션 페치 조인 (0) | 2023.02.16 |
| 2월 15일 JPA JPQL 경로 표현식 (0) | 2023.02.15 |
| 2월 15일 JPA JPQL기본 함수 (0) | 2023.02.15 |
| 2월 15일 JPA JPQL 조건식CASE 식 (0) | 2023.02.15 |