Fetch Join을 했는데도 추가 쿼리가 생성되는 문제가 발생하고 있다.
...
return Optional.ofNullable(jpaQueryFactory
.selectFrom(reservation)
.innerJoin(user).on(reservation.user.id.eq(user.id)).fetchJoin()
.innerJoin(ticketSchedule).on(reservation.ticketSchedule.id.eq(ticketSchedule.id)).fetchJoin()
.where(conditions)
.fetchOne());
}
Hibernate:
select
r1_0.id,
r1_0.cancelled_at,
r1_0.created_at,
r1_0.reservation_name,
r1_0.reservation_number,
r1_0.reservation_phone,
r1_0.status,
r1_0.ticket_schedule_id,
r1_0.total_amount,
r1_0.total_quantity,
r1_0.updated_at,
r1_0.user_id
from
reservation r1_0
join
user u1_0
on r1_0.user_id=u1_0.id
join
ticket_schedule ts1_0
on r1_0.ticket_schedule_id=ts1_0.id
where
r1_0.id=?
and u1_0.email=?
Hibernate:
select
ts1_0.id,
ts1_0.created_at,
ts1_0.is_active,
ts1_0.quantity,
ts1_0.remaining_quantity,
ts1_0.start_date,
ts1_0.start_time,
ts1_0.ticket_id,
ts1_0.updated_at
from
ticket_schedule ts1_0
where
ts1_0.id=?
연관 관계 매핑이 되었는데도 Fetch Join이 올바르게 적용되지 않았던 이유는 on 조건으로 Join을 하였기 때문이다.
Fetch Join은 Select된 루트 Entity와 직접 관계가 매핑되었을 때만 동작한다.
.innerJoin(user).on(reservation.user.id.eq(user.id)).fetchJoin()
.innerJoin(ticketSchedule).on(reservation.ticketSchedule.id.eq(ticketSchedule.id)).fetchJoin()
JPQL을 사용해 Fetch Join을 했을 때처럼 on 조건을 사용하지 않으면 된다.
@Query("select r from Reservation r inner join fetch r.user u where u.email = :email")
List<Reservation> findAllByEmail(String email);
또한, 연관된 Entity를 한 번에 가져오기 위해 Fetch Join을 사용하는 것인데 DTO projection을 사용한 경우에는 DTO를 바로 가져오기 때문에 Fetch Join을 사용하는 의미가 없다.
@Getter
public class PartnerSimpleResDto {
private final Long userId;
private final Long partnerId;
private final String partnerName;
private final String businessNumber;
private final LocalDateTime createdAt;
@QueryProjection
public PartnerSimpleResDto(Long userId, Long partnerId, String partnerName, String businessNumber, LocalDateTime createdAt) {
this.userId = userId;
this.partnerId = partnerId;
this.partnerName = partnerName;
this.businessNumber = businessNumber;
this.createdAt = createdAt;
}
}
.select(new QPartnerSimpleResDto(
user.id,
partner.id,
user.displayName,
partner.businessNumber,
user.createdAt
))
.from(partner)
.innerJoin(user).on(partner.user.id.eq(user.id)).fetchJoin()
.innerJoin(reservation.user, user).fetchJoin()
.innerJoin(reservation.ticketSchedule, ticketSchedule).fetchJoin()
Hibernate:
select
r1_0.id,
r1_0.cancelled_at,
r1_0.created_at,
r1_0.reservation_name,
r1_0.reservation_number,
r1_0.reservation_phone,
r1_0.status,
r1_0.ticket_schedule_id,
ts1_0.id,
ts1_0.created_at,
ts1_0.is_active,
ts1_0.quantity,
ts1_0.remaining_quantity,
ts1_0.start_date,
ts1_0.start_time,
ts1_0.ticket_id,
ts1_0.updated_at,
r1_0.total_amount,
r1_0.total_quantity,
r1_0.updated_at,
r1_0.user_id,
u1_0.id,
u1_0.created_at,
u1_0.display_name,
u1_0.email,
u1_0.is_deleted,
u1_0.password,
u1_0.phone,
u1_0.role,
u1_0.updated_at
from
reservation r1_0
join
user u1_0
on u1_0.id=r1_0.user_id
join
ticket_schedule ts1_0
on ts1_0.id=r1_0.ticket_schedule_id
where
r1_0.id=?
and u1_0.email=?