문제 코드
List<TodoPageResponse> list = queryFactory
.select(Projections.constructor(
TodoPageResponse.class),
todo.title,
todo.managers.size(),
todo.comments.size())
.from(todo)
.leftJoin(todo.managers)
.leftJoin(todo.comments)
.where(
titleCont(request.getTitle()),
dateEq(start, end),
nicknameCont(request.getNickname())
)
.groupBy(todo.id)
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
//밑에 이런 식으로 console 에러 발생
Could not interpret path expression 'manager'
count()를 사용하지 않고 size()를 사용하면 위험count()와 countDistinct()를 사용 해야 함수정된 코드
List<TodoPageResponse> list = queryFactory
.select(Projections.constructor(
TodoPageResponse.class,
todo.title,
manager.countDistinct(),
comment.countDistinct())
)
.from(todo)
.leftJoin(todo.managers, manager)
.leftJoin(todo.comments, comment)
.where(
titleCont(request.getTitle()),
dateEq(start, end),
nicknameCont(request.getNickname())
)
.groupBy(todo.id)
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
Long listCount = queryFactory
.select(todo.count())
.from(todo)
.leftJoin(todo.managers, manager)
.leftJoin(todo.comments, comment)
.where(
titleCont(request.getTitle()),
dateEq(start, end),
nicknameCont(request.getNickname())
)
.groupBy(todo.id)
.fetch();
Query did not return a unique result: 6 results were returned
해결된 코드
Long listCount = queryFactory
.select(todo.count())
.from(todo)
.leftJoin(todo.managers, manager)
.leftJoin(todo.comments, comment)
.where(
titleCont(request.getTitle()),
dateEq(start, end),
nicknameCont(request.getNickname())
)
.fetchOne();
QueryDSLpublic Page<TodoPageResponse> findAllWithCond(TodoPageRequest request) {
Pageable pageable = PageRequest.of(request.getPage(), request.getSize());
LocalDateTime start = null;
LocalDateTime end = null;
if (request.getStartDate() != null) start = request.getStartDate().atStartOfDay();
if (request.getEndDate() != null) end = request.getEndDate().plusDays(1).atStartOfDay();
List<TodoPageResponse> list = queryFactory
.select(Projections.constructor(
TodoPageResponse.class,
todo.title,
manager.countDistinct(),
comment.countDistinct())
)
.from(todo)
.leftJoin(todo.managers, manager)
.leftJoin(todo.comments, comment)
.where(
titleCont(request.getTitle()),
dateEq(start, end),
nicknameCont(request.getNickname())
)
.groupBy(todo.id)
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
Long listCount = queryFactory
.select(todo.count())
.from(todo)
.leftJoin(todo.managers, manager)
.leftJoin(todo.comments, comment)
.where(
titleCont(request.getTitle()),
dateEq(start, end),
nicknameCont(request.getNickname())
)
.fetchOne();
long total = listCount != null ? listCount : 0L;
return new PageImpl<>(list, pageable, total);
}
//제목 부분 일치 확인
private BooleanExpression titleCont(String title) {
return title == null ? null : todo.title.contains(title);
}
//생성일 범위 확인
private BooleanExpression dateEq(LocalDateTime startDate, LocalDateTime endDate) {
if(startDate != null && endDate != null) return todo.createdAt.between(startDate, endDate);
else if (startDate != null) return todo.createdAt.goe(startDate);
else if (endDate != null) return todo.createdAt.loe(endDate);
else return null;
}
//담당자 닉네임 부분 확인
private BooleanExpression nicknameCont(String nickname) {
return nickname == null ? null : manager.user.nickname.contains(nickname);
}
Controller@GetMapping("/todos/d")
public ResponseEntity<Page<TodoPageResponse>> getTodoPage(TodoPageRequest request) {
return ResponseEntity.ok(todoService.getTodoPage(request));
}
Service@Transactional(readOnly = true)
public Page<TodoPageResponse> getTodoPage(TodoPageRequest request) {
return todoRepository.findAllWithCond(request);
}
Request@Getter
public class TodoPageRequest {
private final String title;
private final LocalDate startDate;
private final LocalDate endDate;
private final String nickname;
private final Integer page;
private final Integer size;
public TodoPageRequest(String title,
LocalDate startDate,
LocalDate endDate,
String nickname,
Integer page,
Integer size) {
this.title = title;
this.startDate = startDate;
this.endDate = endDate;
this.nickname = nickname;
this.page = page == null ? 0 : page;
this.size = size == null ? 10 : size;
}
}
page와 size를 defaultValue를 설정API를 만들어서 일정을 검색하는 기능을 구현Projections를 활용해서 필요한 필드만 페이징 반환Could not interpret path expression 'manager.user.nickname’ 에러 발생join users u1_0 on u1_0.id = m1_0.user_id으로 쿼리를 날림# nickname 만 검색했을 때
select t1_0.title,
count(distinct m1_0.id),
count(distinct c1_0.id)
from todos t1_0
left join managers m1_0 on t1_0.id = m1_0.todo_id
join users u1_0 on u1_0.id = m1_0.user_id
left join comments c1_0 on t1_0.id = c1_0.todo_id
where u1_0.nickname like ? escape '!'
group by t1_0.id
order by t1_0.created_at desc
limit ?, ?
# title과 nickname을 검색했을 때
select t1_0.title,
count(distinct m1_0.id),
count(distinct c1_0.id)
from todos t1_0
left join managers m1_0 on t1_0.id=m1_0.todo_id
join users u1_0 on u1_0.id=m1_0.user_id
left join comments c1_0 on t1_0.id=c1_0.todo_id
where t1_0.title like ? escape '!'
and u1_0.nickname like ? escape '!'
group by t1_0.id order by t1_0.created_at desc limit ?,?
List<TodoPageResponse> list = queryFactory
.select(Projections.constructor(
TodoPageResponse.class,
todo.title,
manager.countDistinct(),
comment.countDistinct())
)
.from(todo)
.leftJoin(todo.managers, manager)
.leftJoin(manager.user, user)
.leftJoin(todo.comments, comment)
.where(
titleCont(request.getTitle()),
dateEq(start, end),
nicknameCont(request.getNickname())
)
.groupBy(todo.id)
.orderBy(todo.createdAt.desc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
//담당자 닉네임 부분 확인
private BooleanExpression nicknameCont(String nickname) {
return nickname == null ? null : user.nickname.contains(nickname);
}