Place(장소)
entity와 PlaceImage(장소)
entity가 지연 로딩(FetchType.LAZY)
되어있습니다.
Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Place extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
@OneToMany(mappedBy = "place", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, orphanRemoval = true)
private List<PlaceImage> images = new ArrayList<>();
@Entity
@Table(name = "place_img")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class PlaceImage extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "place_id")
private Place place;
이 때 특정 Place를 조회할 때 Place와 연관된 PlaceImage 중 1개만 fetch join 하고싶은 상황입니다.
단순히 특정 Place에 연관된 PlaceImage 모두를 fetch join한 뒤 그 결과 중 하나를 선택해도 해결은 가능합니다.
@Query("select p
from Place p
left join fetch p.images
where p.id = :id")
List<Place> findOneByIdFetchImage(@Param("id") Long id);
하지만 연관된 PlaceImage가 매우 많을 수도 있는 상황에서는 비효율적일 것이라 생각했습니다.
따라서 limit 1
과 같은 효과를 얻기 위해 Pageable
을 사용했습니다.
@Query("select p
from Place p
left join fetch p.images
where p.id = :id")
List<Place> findOneByIdFetchImage(@Param("id") Long id, Pageable pageable);
PageRequest.of(0, 1)
를 파라미터로 넘겨 offset은 0, pageSize는 1
이 되어 limit 1의 효과
를 볼 수 있습니다.
public List<Place> findOneByIdFetchImage(Long id) {
return placeRepository.findOneByIdFetchImage(id, PageRequest.of(0, 1));
}
select
p1_0.id,
...
p2_0.id,
...
from
place p1_0
left join
place_img p2_0
on p1_0.id=p2_0.place_id
where
p1_0.id=? offset ? rows fetch first ? rows only