JPAQueryFacotry, EntityManager를 통해 빈으로 등록해놓은 상태이다. Querydsl에 대한 설정을 마친 후 Entity에 대한 Q클래스들이 생성되어 있다.
@Override
public List<Tuple> searchList(OneononeFilterDto oneononeFilterDto) {
List<Tuple> result=queryFactory
.select(oneononeInquiry,categoryAdmin.administratorId,employeeInterfaceReceive.userName,nomemberInquiry.writerName, Expressions.as(
JPAExpressions.select(oneononeInquiry.registProcessDayandtime)
.from(selfJoinInquiry)
.where( oneononeInquiry.uponeononeInquirySequencenumber.isNotNull(),
oneononeInquiry.oneononeInquirySequencenumber.eq(selfJoinInquiry.oneononeInquirySequencenumber)),
"lastAnswerDay")
)
.from(oneononeInquiry)
.join(categoryAdmin)
.on(oneononeInquiry.customercenterCategoryCode.eq(categoryAdmin.customercenterCategoryCode))
.join(categoryAdmin.employeeInterfaceReceive,employeeInterfaceReceive)
.join(oneononeInquiry.nomemberInquiry,nomemberInquiry)
.fetchJoin()
.where(
OneononeInquiryRepositoryUtil.eqServiceType(oneononeFilterDto.getServiceType()),
OneononeInquiryRepositoryUtil.inCategoryTypeList(oneononeFilterDto.getCategoryTypeList()),
OneononeInquiryRepositoryUtil.containSearchCategory(oneononeFilterDto.getSearchCategory(), oneononeFilterDto.getSearchKeyword())
)
.orderBy(OneononeInquiryRepositoryUtil.orderByReferenceDayFirst(oneononeFilterDto.getReferenceDay()),OneononeInquiryRepositoryUtil.orderByReferenceDaySecond(oneononeFilterDto.getReferenceDay()))
.fetch();
return result;
}
Querydsl이 지원하는 Tuple타입으로 리턴을 받을 수 있다.
해당 코드 Tuple 내부에는 Entity,String,String,String,String 형식으로 값이 저장되어 있다.
@Test
@DisplayName("쿼리 테스트")
public void 쿼리테스트(){
QOneononeInquiry oneononeInquiry = QOneononeInquiry.oneononeInquiry;
List<OneononeInquiryBoardDto> dtoList = new ArrayList<>();
OneononeFilterDto oneononeFilterDto = makeTestCase("","전체","ST04","전체","","2022-12-12","전체","a");
List<Tuple> oneononeInquiryList = oneononeInquiryRepositoryImpl.searchList(oneononeFilterDto);
oneononeInquiryList
.stream()
.forEach(item -> dtoList.add(oneonOneInquiryMapper.toDto(item.get(oneononeInquiry))));
for(int i=0;i<dtoList.size();i++){
dtoList.get(i).setAdministratorId(oneononeInquiryList.get(i).get(1,String.class));
dtoList.get(i).setUserName(oneononeInquiryList.get(i).get(2,String.class));
dtoList.get(i).setWriterName(oneononeInquiryList.get(i).get(3,String.class));
dtoList.get(i).setLastAnswerDay(oneononeInquiryList.get(i).get(4,String.class));
}
assertEquals(dtoList.size(),20);
}
Test코드 순서를 보면 다음과 같다
1.Entity를 mapstruct를 이용해 Dto로 변환한다.
2.List에 Tuple로 받은 String값을 세팅한다.
Dto를 Repository의 영역까지 끌고오지 않고 Entity와 추가적인 필요 정보만을 Service로 가져와 처리하지만 코드가 길어지게 된다.
또한 Tuple내부의 유추를 위해 Expression,Class를 명시해야 하는데 QClass 객체가 필요하고 String.class로 접근하는 방식이 조금 불편하다.
@Override
public List<OneononeInquiryBoardDto> searchList(OneononeFilterDto oneononeFilterDto) {
return queryFactory
.select(Projections.fields(OneononeInquiryBoardDto.class,
oneononeInquiry.oooInqrySno,
oneononeInquiry.chnlDvcd,
oneononeInquiry.custmctCtgrCd,
oneononeInquiry.ttl,
oneononeInquiry.custmctProcStacd,
oneononeInquiry.rgstProcrId,
oneononeInquiry.rgstProcDtm,
categoryAdmin.admrID,
Expressions.as(
JPAExpressions.select(oneononeInquiry.rgstProcDtm)
.from(selfJoinInquiry)
.where( oneononeInquiry.upOooInqrySno.isNotNull(),
oneononeInquiry.oooInqrySno.eq(selfJoinInquiry.oooInqrySno)),
"lastAnswerDay")
))
.from(oneononeInquiry)
.join(oneononeInquiry.categoryAdmin,categoryAdmin)
.where(
OneononeInquiryRepositoryUtil.eqServiceType(oneononeFilterDto.getServiceType()),
OneononeInquiryRepositoryUtil.inCategoryTypeList(oneononeFilterDto.getCategoryTypeList()),
OneononeInquiryRepositoryUtil.containSearchCategory(oneononeFilterDto.getSearchCategory(), oneononeFilterDto.getSearchKeyword())
)
.orderBy(OneononeInquiryRepositoryUtil.orderByReferenceDayFirst(oneononeFilterDto.getReferenceDay()),OneononeInquiryRepositoryUtil.orderByReferenceDaySecond(oneononeFilterDto.getReferenceDay()))
.fetch();
}
Projection을 통해 다양한 방법으로 조회가 가능하다. 세부내용은 추후 다뤄봐야겠다.
Dto를 Repository의 영역으로 끌고와서 정말 필요한 것들만 select하여 Mapping후 Service로 리턴한다.
@Test
@DisplayName("쿼리 테스트")
public void 쿼리테스트(){
List<OneononeInquiryBoardDto> dtoList = new ArrayList<>();
OneononeFilterDto oneononeFilterDto = makeTestCase("","전체","ST04","전체","","2022-12-12","전체","a");
List<OneononeInquiryBoardDto> oneononeInquiryList= oneononeInquiryRepositoryImpl.searchList(oneononeFilterDto);
assertEquals(oneononeInquiryList.size(),20);
}
Test코드는 보는것과 같이 List로 받아오고 끝이다.
Tuple로 받은 방식보다 훨씬 코드가 간결하고 Repository 영역에서 어떤것을 조회하는지도 보기가 쉽다.
성능, 리팩토링 면에서는 후자가 더 좋다. Dto가 Repository 영역에 존재하여 무결성이 위반되는 상황이 생기는 경우에 대해 공부 해봐야겠다.