흔히 사용하는 SQL에서의 JOIN기능이 아닙니다.
조회하는 엔티티에 연관괸 엔티티를 한번에 함께 조회 하는 기능!
?? 뭔 말?
이 전시간에 프록시에 대해서 배워봤습니다.
프록시의 기능으로 인해서 연관된 엔티티를 조회할 때 쿼리가 N+1개가 날아가
성능이 저하되는 모습을 보였습니다! 이를 해결하기 위해
한방 쿼리로 연관된 엔티티를 한번에 함께 조회 한다고 생각 하시면 되겠습니다.
프록시 및 자세한 내용이 궁금하시면 JPA - 프록시(즉시로딩 VS 지연로딩)를 확인 해 주세요 : )
예시
Member Entity
@Entity
public class Member {
@Id @GeneratedValue
@Column(name="member_id")
private Long id;
private String name;
@ManyToOne
@JoinColum((insertable=false, updatable=false)
private Team team
}
Team Entity
@Entity
public class Team {
@Id @GeneratedValue
@Column(name="team_id")
private Long id;
private String name;
@OneToMany
@JoinColumn(name="member_id")
private List<Member> members= new ArrayList<Member>();
}
이와같은 엔티티가 있다고 생각 합시다.
Member Entity를 조회할 때 Team Entity도 한번에 조회하고 싶다?!
SELECT m FROM Member m join fetch m.team;
이와 같은 fetch join기능을 사용하시면 됩니다!
중요한 점!
위의 JPQL은 N:1 관계에서의 Member Entity에서 fetch join을 보여드리고 있습니다. 그렇다면, 1:N 관계에서의 Team Entity에서 연관된 Entity인 Member Entity를 같이 조회하기 위해 fetch join기능을 사용하면 어떻게 될까요?
그냥 DB 테이블에서 JOIN하는 경우를 생각 해 봅시다!
SELECT t FROM Tema t join fetch t.members;
이렇게 JPQL을 날리게 되면 테이블이 뻥튀기 됐기 때문에, team_id가 1인 Team Entity가 2번 조회되어 리스트에 담길 것입니다..
해결 방안
JPQL에서는 이러한 문제의 해결 방안으로 distinct라는 기능을 제공합니다.
SELECT distinct t FROM Tema t join fetch m.member;
이렇게 사용하시면 됩니다!
일반 SQL이었다면 위의 테이블에서 두 인스턴스가 완벽히 중복이 아니기 때문에 중복 결과를 제거하지 못할 것입니다.
하지만, JPQL이기 때문에 같은 식별자를 가진 Team엔티티를 제거하여 조회를 하게 됩니다!
Fetch Join의 한계
테이블이 뻥튀기 되었던 상황을 고려하면 컬렉션 fetch join시, 페이징이 왜 안되는지는 당연한 결과와 같습니다.
이 글은 인프런 김영한님의 '자바 ORM 표준 JPA 프로그래밍 - 기본편'을 수강하고 작성합니다.
출처:https://www.inflearn.com/course/ORM-JPA-Basic
고생하셨읍니다~ 좋은 정보 잘 얻고 갑니다 ~~!