Fetch Join은 기본 SQL 문법이 아니다.
JPQL( Java Persistence Query Language)에서 성능 최적화를 위해 제공하는 기능이다.
연관 Entity or Collection을 SQL 한 번에 조회하기 위해 사용된다.
JPQL ( Java Persistence Query Language ) : 객체 지향 쿼리 언어
- 테이블 대상으로 쿼리를 하는것이 아닌 객체를 대상으로 쿼리
- SQL를 추상화한 것으로 특정 DB의 SQL에 의존하지 않는다
보통 아래와 같은 형태로 사용된다.
@Query("select m from Member m join fetch m.team")
실제 사용되는 예시를 보도록하자.
Member, Team Entity가 존재하고 Member는 하나의 Team에 속할 수 있고 Team은 여러 명의 Member를 가질 수 있다.
위와 같은 형태로 Member의 정보를 조회했을 때 해당 Member가 속한 Team 정보를 조회하고 싶은 경우에 사용될 수 있다.
@Getter
@NoArgsConstructor
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
private String name;
@ManyToOne
private Team team;
@Builder
public Member(String name) {
this.name = name;
}
public void updateTeam(Team team) {
this.team = team;
}
}
@Getter
@NoArgsConstructor
@Entity
public class Team {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
private String name;
@OneToMany(mappedBy = "team")
private List<Member> members;
@Builder
public Team(String name) {
this.name = name;
}
}
기본적으로 JPA에서 제공하는 findAll 메서드를 호출하게 되면 Member List를 모두 조회해오는 Query와 각각의 Member에 매핑되는 Team을 조회하는 쿼리가 실행하게 된다.
( 예를 들어 Member의 개수가 N 인 경우 Member List 조회 ( 1 ) + 각 Member에 매핑되는 Team 조회 ( N ) => N +1 )
memberRepository.findAll()
Hibernate:
select member0_.id as id1_2_, member0_.name as name2_2_, member0_.team_id as team_id3_2_ from Member member0_
Hibernate:
select team0_.id as id1_6_0_, team0_.name as name2_6_0_ from Team team0_ where team0_.id=?
Hibernate:
select team0_.id as id1_6_0_, team0_.name as name2_6_0_ from Team team0_ where team0_.id=?
이러한 문제를 해결하기 위해서 JPQL에서 Fetch Join 기능을 제공한다.
public interface MemberRepository extends JpaRepository<Member, Long>{
@Query("select m from Member m join fetch m.team")
Set<Member> findAllJoinFetch();
}
memberRepository.findAllJoinFetch()
Hibernate:
select
member0_.id as id1_2_0_,
team1_.id as id1_6_1_,
member0_.name as name2_2_0_,
member0_.team_id as team_id3_2_0_,
team1_.name as name2_6_1_
from
Member member0_
inner join
Team team1_
on member0_.team_id=team1_.id
만약 실행되는 Query의 Join 형식도 정하고 싶은 경우에는 아래와 같이 지정하면 된다.
@Query("select m from Member m left join fetch m.team")
또한 Join을 한 대상에서 한 번 더 Join을 하고 싶은 경우에는 아래와 같이 작성하면 된다.
( Team에 연관 객체로 Coach가 있다고 가정 )
@Query("select m from Member m join fetch m.team t join fetch t.coach")
만약 이러한 형태가 아닌 기본 제공하는 findAll을 통해서 연관 객체를 조회하고 싶은 경우에는 FetchType을 EAGER로 지정하면 된다.
@Getter
@NoArgsConstructor
@Entity
public class Team {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
private String name;
@OneToMany(mappedBy = "team", fetch = FetchType.EAGER) // !!Added
private List<Member> members;
@Builder
public Team(String name) {
this.name = name;
}
}
'Spring JPA' 카테고리의 다른 글
[JPA] SQL View - JPA Entity 매핑 (0) | 2022.01.20 |
---|---|
[JPA] 복합키 (Composite Key) - @IdClass, @EmbeddedId (0) | 2022.01.15 |
[JPA] 일대다 @OneToMany 연관관계 매핑(1:N) (0) | 2021.08.05 |
[JPA] 일대일 @OneToOne 연관관계 매핑(1:1) (0) | 2021.07.27 |
[JPA] 연관관계 매핑 관련 용어 정의 (0) | 2021.07.20 |