@Override
public Page<Meeting> getMeetingsQueryDsl(Double locationLat, Double locationLng, Pageable pageable) {
QMeeting meeting = QMeeting.meeting;
List<Meeting> meetingList = queryFactory
.selectFrom(meeting)
.orderBy(distanceExpression(locationLat, locationLng).asc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
Long total = queryFactory
.select(meeting.count())
.from(meeting)
.fetchOne();
long totalCount = total != null ? total : 0L;
return new PageImpl<>(meetingList, pageable, totalCount);
}
private ComparableExpressionBase<Double> distanceExpression(Double locationLat, Double locationLng) {
return Expressions.numberTemplate(Double.class,
"ST_DISTANCE_SPHERE(point({0}, {1}), point(meeting.locationLng, meeting.locationLat))",
locationLng, locationLat);
}
→ Where 안에 null 값이 들어가는 경우, Query에서 무시
→ join의 경우, null이 들어가면 404
→ .leftjoin을 skill ID 혹은 career ID 가 null / isEmpty()인 경우에도 수행한다면, 이 경우의 수를 분기처리해야 하는 것인지, QueryDsl 기능으로 처리가 가능한지 확인 중
@Override
public Page<Meeting> getMeetingsWithSkillAndCareer(Double locationLat, Double locationLng, List<Long> skillId, List<Long> careerId, Pageable pageable) {
QMeeting meeting = QMeeting.meeting;
QMeetingSkill meetingSkill = QMeetingSkill.meetingSkill;
QMeetingCareer meetingCareer = QMeetingCareer.meetingCareer;
List<Meeting> meetingList = queryFactory.selectFrom(meeting)
.leftJoin(meetingSkill).on(meeting.Id.eq(meetingSkill.meeting.Id))
.leftJoin(meetingCareer).on(meeting.Id.eq(meetingCareer.meeting.Id))
.where(
meetingSkill.meeting.Id.in(skillId),
meetingCareer.career.Id.in(careerId)
)
.orderBy(distanceExpression(locationLat, locationLng).asc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
Long total = queryFactory.select(meeting.count())
.from(meeting)
.leftJoin(meetingSkill).on(meeting.Id.eq(meetingSkill.meeting.Id))
.leftJoin(meetingCareer).on(meeting.Id.eq(meetingCareer.meeting.Id))
.where(
meetingSkill.meeting.Id.in(skillId),
meetingCareer.career.Id.in(careerId)
)
.fetchOne();
long totalCount = total != null ? total : 0L;
return new PageImpl<>(meetingList, pageable, totalCount);
}
→ List<Long> skillId, List<Long> careerId 둘 다 값을 입력하지 않은 경우 ⇒ 404
"errorMessage": "Cannot invoke \\"java.util.Collection.size()\\" because \\"right\\" is null"
❓ ‘동적 쿼리를 제어하기 위한 QueryDsl’에서 Join을 어떻게 제어해야 하는가?
→ 결론: 동적 쿼리에 대한 제어는 Where절 안에서 이루어지는 것이며, Where를 걸기 위한 조건이 Join이라면, 아래의 예제처럼 분기 처리가 필요하다.
(❗Join의 형태가 다양한 경우이므로, 우리 상황과 맞지 않다고 생각됩니다.)
@Override
public List<Tuple> findTestListByCondition(AdminTestListConditionRequest condition) {
Check check = Check.valueOf(condition.getCheck());
List<Tuple> result = null;
switch (check) {
//CORRECT(테스트 맞은 정보만 가져오기)
case CORRECT:
result = queryFactory
.select(adminSentence.id, adminSentence.korean,
adminSentence.english, adminSentence.grammar, adminSentence.situation,
adminTestCheck.testCheck)
.from(adminSentence)
.where(grammarEq(condition.getGrammar()), situationEq(condition.getSituation()))
.innerJoin(adminSentence.adminTestChecks, adminTestCheck)
//이너 조인을 하고 on 조건에
//해당 userId가 일치하고
//check 정보가 correct인 정보만 가져오기
.on(adminTestCheck.testCheck.eq(check),
adminTestCheck.users.id.eq(condition.getUserId()))
.fetch();
break;
//NO(맞거나 틀리거나 테스트보지않았거나 - 모든 정보 가져오기)
case NO:
result = queryFactory
.select(adminSentence.id, adminSentence.korean,
adminSentence.english, adminSentence.grammar, adminSentence.situation,
adminTestCheck.testCheck)
.from(adminSentence)
.where(grammarEq(condition.getGrammar()), situationEq(condition.getSituation()))
//left outer join으로
//userId가 일치하는 모든 문장 가져온다.
.leftJoin(adminSentence.adminTestChecks, adminTestCheck)
.on(adminTestCheck.users.id.eq(condition.getUserId()))
.fetch();
break;
//WRONG(틀리거나 테스트보지않은 정보만 가져오기)
case WRONG:
result = queryFactory
.select(adminSentence.id, adminSentence.korean,
adminSentence.english, adminSentence.grammar, adminSentence.situation,
adminTestCheck.testCheck)
.from(adminSentence)
.where(grammarEq(condition.getGrammar()), situationEq(condition.getSituation())
, adminTestCheck.isNull().or(adminTestCheck.testCheck.eq(Check.WRONG))
)
//left outer join으로 check 정보가 없는 문장도 전부
//가져오는데,
//가져온 정보 중에 where 조건 절로 check 정보가 CORRECT가
//아닌 정보만 가져오게 설정한다.
.leftJoin(adminSentence.adminTestChecks, adminTestCheck)
.on(adminTestCheck.users.id.eq(condition.getUserId()))
.fetch();
break;
}
return result;
}