부모 Entity인 Faq가 자식 Entity인 FaqImage를 List로 가지고 있을 때, Faq를 조회할 때 FaqImage를 프론트에 어떻게 보내줄까?
faqRespository.findByFaqId(faqId)
로 faq 객체를 한번 찾고,faqImageRepository.findAllByFaqId(faqId)
를 찾아서Response 객체
에 담아주는 방법도 있을것이다.그러나 그러면 불필요하게 select 구문이 두번 날아가는 것을 확인할 수 있을 것이다.
그러면 네이티브 쿼리로 직접 join 구문을 명시해둬서 가져오기? 그러면 JPA를 사용하는 이유가 떨어질 것이다.
DTO
@Getter @Setter @Builder @NoArgsConstructor @AllArgsConstructor public class FaqDTO { private Integer faqId; // 고유 번호 private Integer adminId; // 작성한 관리자 고유 번호 private String faqTitle; // 제목 private String faqContent; // 내용 // 아래부턴 자식 Entity 내용들 private Integer imageId; private String imageUrl; private Integer sort; }
FaqCustomRepositoryImpl
@Override public List<FaqDTO> findFaqInfo(Integer faqId) { List<FaqDTO> result = queryFactory .select(Projections.constructor(FaqDTO.class, faq.faqId, faq.adminId, faq.faqTitle, faq.faqContent, faqImage.id, faqImage.faqFileUrl, faqImage.sort)) .from(faq) .leftJoin(faqImage).on(faq.faqId.eq(faqImage.faq.faqId)) .where(faq.faqId.eq(faqId)) .orderBy(faqImage.sort.asc()) .fetch(); return result; }
이런식으로 QueryDSL를 짜줘도 문제는 없다! 연관관계가 맺어져있어서 알아서 잘 찾아오기 때문. 단지 문제는... 👇
.select(Projections.constructor(FaqDTO.class,
시에 자식 객체를 자동으로 List로 변환해주지 않는다. 그말은 즉 !
아래처럼 부모 객체 하나 조회시 자식 객체 개수 만큼, 자식 객체 하나에 부모객체가 늘 같이 불러온다는 뜻이다. 프론트 입장에서는....중복되는 데이터들에 짜증날 것 같다. 또한 Json이 길어지면 그만큼 속도나 네트워크 비용에서도 문제가 있겠지...?
DTO
@Getter @Setter @Builder @NoArgsConstructor @AllArgsConstructor public class FaqDTO { private Integer faqId; // 고유 번호 private Integer adminId; // 작성한 관리자 고유 번호 private String faqTitle; // 제목 private String faqContent; // 내용 private List<FaqImageDTO> faqImagesUrl; // 이미지 URL }
FaqCustomRepositoryImpl
@Override public List<FaqDTO> findFaqInfo(Integer faqId) { List<FaqDTO> result = queryFactory .selectFrom(faq) .leftJoin(faqImage).on(faq.faqId.eq(faqImage.faq.faqId)) .where(faq.faqId.eq(faqId)) .orderBy(faqImage.sort.asc()) .transform(groupBy(faq.faqId).list(Projections.constructor(FaqDTO.class, faq.faqId, faq.adminId, faq.faqTitle, faq.faqContent, list(Projections.constructor(FaqImageDTO.class, faqImage.id, faqImage.faqFileUrl, faqImage.sort) )))); return result; }
이런식으로.transform(groupBy(faq.faqId).list(
이용해주면 부모객체 하나에 자식객체를 리스트로 붙여서 반환할 수 있다.
여기서 주의!!! 안에 list
는 import static com.querydsl.core.group.GroupBy.list; 를 임포트 해서 써줘야 한다 : )
아주 멋지십니다~