먼저 join 과 fetch join의 차이점을 알아보자
조회의 주체가 되는 엔티티에만 select해서 영속화를 하기 때문에 연관 엔티티의 데이터는 필요가 없으나 연관 엔티티가 검색 조건에 필요할 경우 주로 사용된다.
아래의 Member엔티티와 Order엔티티 예시를 보자
@Entity
@Getter
@Setter
public class Member {
@Id
@GeneratedValue
private long id;
@Column
private String name;
@Column
private String email;
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<>();
public void addOrders(Order order) {
this.orders.add(order);
if(order.getMember() != this) {
order.setMember(this);
}
}
}
아이디 | 이름 | 이메일 |
---|---|---|
1 | 김유신 | abc1@example.com |
2 | 이순신 | abc2@example.com |
3 | 유관순 | abc3@example.com |
@Entity
@Getter
@Setter
public class Order {
@Id
@GeneratedValue
private long id;
@Column
private String date;
@ManyToOne
@JoinColumn(name = "memberId")
private Member member;
public void setMember(Member member) {
this.member = member;
if(!member.getOrders().contains(this) {
member.getOrders().add(this);
}
}
}
아이디 | 주문날짜 | MemberId |
---|---|---|
1 | 20220102 | 1 |
2 | 20220103 | 2 |
3 | 20220104 | 2 |
4 | 20220104 | 3 |
(Member와 Order는 1 : N 관계이다)
SELECT m FROM Member m JOIN m.Order
Hibernate:
select
distinct member0_.id as id1_1_,
member0_.name as name2_1_
member0_.email as email2_1_
from member member0_
inner join
order order1_
on member0_.id=order1_.member_id
아이디 | 이름 | 이메일 |
---|---|---|
1 | 김유신 | abc1@example.com |
Member와 Order가 Join된 형태의 쿼리가 실행된다.Member의 컬럼과 해당되는 Order까지 select 될 것 같지만 가져오는 컬럼은 Member의 컬럼인 ID, name, email 만 가져오고 있다.
일반 join은 실제 쿼리에 join을 걸어주나 join대상의 영속성에는 관여하지 않고 join대상 엔티티는 초기화 하지 않는다.
SELECT m FROM Member m JOIN FETCH m.Order
Hibernate:
select
distinct member0_.id as id1_1_,
order1_.id as id1_0_1_,
member0_.name as name2_1_,
member0_.email as email2_1_,
order1_.date as date2_0_1
from member member0_
inner join
order order1_
on member0_.id=order1_.member_id
아이디 | 이름 | 이메일 | 주문 아이디 | 주문 날짜 |
---|---|---|---|---|
1 | 김유신 | abc1@example.com | 1 | 20220102 |
일반 Join과 달리 Fetch Join은 실제 질의하는 대상 엔티티와 fetch join이 걸린 엔티티를 포함한 컬럼을 함께 select 한다.
Member id, name, email 뿐만 아니라 그 안에 해당되는 Order 까지 select 된다.