[1] Service 설정
Todo를 get, register, modify하는 구조가 필요하다.
@Service
@Log4j2
@RequiredArgsConstructor
public class TodoServiceImpl implements TodoService{
private final TodoRepository todoRepository;
@Override
public TodoDTO get(Long tno){
Optional<Todo> result = todoRepository.findById(tno);
Todo todo = result.orElseThrow();
return entityDTO(todo);
}
@Override
public Long register(TodoDTO dto) {
Todo todo = dtoToEntity(dto);
Todo result = todoRepository.save(todo);
return result.getTno();
}
@Override
public void modify(TodoDTO dto) {
Optional<Todo> result = todoRepository.findById(dto.getTno());
Todo todo = result.orElseThrow();
todo.changeTitle(dto.getTitle());
todo.changeContent(dto.getContent());
todo.changeComplete(dto.isComplete());
todo.changeDueDate(dto.getDueDate());
todoRepository.save(todo);
}
@Override
public void remove(Long tno) {
todoRepository.deleteById(tno);
}
}
[2] PageResponseDTO -- 페이지 넘어가는 로직 설계
[2-1] start & end & last
ex) 3페이지 조회: 1~10 반환, 11페이지 조회: 11~20 반환
(3 / 10 = 0.3을 올림 ) * 10-> end (10)
end에서 9를 빼면 항상 -> start (1)
ex) 전체 132페이지에서 13 페이지 조회: end 값은 20 , 실제로는 14 까지 밖에 없음
따라서 end>last면 last로 하기
[2-2] prev & next
이전, 다음 페이지가 있는지 bool
[2-3]
페이지 목록 ex) 1...10 생성
@Data
public class PageResponseDTO <E>{
private List<E> dtoList;
private List<Integer> pageNumberList;
private PageRequestDTO pageRequestDTO;
private boolean prev, next; //페이지 이전, 다음
private int totalCount, prevPage, nextPage, totalPage, current;
@Builder(builderMethodName = "withAll")
public PageResponseDTO(List<E> dtoList, PageRequestDTO pageRequestDTO, long total){
this.dtoList = dtoList;
this.pageRequestDTO = pageRequestDTO;
this.totalCount = (int) total;
//끝 페이지 end
int end = (int) (Math.ceil(pageRequestDTO.getPage() / 10.0)) * 10;
int start = end-9;
//진짜 마지막
int last = (int)(Math.ceil(totalCount / (double) pageRequestDTO.getSize()));
end = end > last ? last : end;
this.prev = start >1;
this.next = totalCount > end * pageRequestDTO.getSize();
this.pageNumberList = IntStream.rangeClosed(start, end).boxed().collect(Collectors.toList());
this.prevPage = prev ? start-1 : 0;
this.nextPage = next ? end+1:0;
}
}
상단의 @Builder(builderMethodName = "withAll")로
PageResponseDTO<UserDTO> response = PageResponseDTO.<UserDTO>withAll()
.dtoList(userList)
.pageRequestDTO(requestDTO)
.total(100L)
.build(); 처럼 설계 가능함
[3] service 설계
[3-1] TodoService interface에 선언
PageResponseDTO<TodoDTO> getList(PageRequestDTO pageRequestDTO);
[3-2] TodoSearch interface에 선언
Page<Todo> search1(PageRequestDTO pageRequestDTO);
[3-3] TodoServiceImpl
@Override
public PageResponseDTO<TodoDTO> getList(PageRequestDTO pageRequestDTO) {
//JPA
Page<Todo> result = todoRepository.search1(pageRequestDTO);
//가져온 Todo List -> TodoDTO List로 만들기
List<TodoDTO> dtoList = result
.get()
.map(todo -> entityDTO(todo)).collect(Collectors.toList());
PageResponseDTO<TodoDTO> responseDTO =
PageResponseDTO.<TodoDTO>withAll()
.dtoList(dtoList)
.pageRequestDTO(pageRequestDTO)
.total(result.getTotalElements())
.build();
return responseDTO;
}
- search1(하단)을 통해 Todo 엔티티 목록을 가져온다.
- result.get() → Stream<Todo>을 반환
- .map(todo -> entityDTO(todo)) → 각 Todo 엔티티를 TodoDTO로 변환
- .collect(Collectors.toList()) → 변환된 TodoDTO 리스트를 List<TodoDTO> 형태로 저장
- 최종적으로 PageResponseDTO<TodoDTO>를 반환해서 프론트에서 쓸 수 있음

[3-4] TodoSearchImpl
@Override
public Page<Todo> search1(PageRequestDTO pageRequestDTO){
log.info("search1..............");
QTodo todo = QTodo.todo; //자동으로 생성한 Q 클래스
JPQLQuery<Todo> query = from(todo); //QueryDSL을 사용하여 JPQL 쿼리 생성
//query.where(todo.title.contains("1"));
//Pageable 실행
Pageable pageable = PageRequest.of(
pageRequestDTO.getPage()-1,
pageRequestDTO.getSize(),
Sort.by("tno").descending());
//Querydsl 사용 !
this.getQuerydsl().applyPagination(pageable, query);
List<Todo> list = query.fetch(); //데이터 가져옴
long total = query.fetchCount();
return new PageImpl<>(list, pageable, total);
}
Spring Data JPA에서 QueryDSL을 사용할 때 페이징을 적용:
this.getQuerydsl() - QueryDSL 인스턴스를 가져오기,
applyPagination(pageable, query) - 페이징을 자동으로 적용
'개발 > Spring' 카테고리의 다른 글
[6] Todo get, register, modify, remove (0) | 2025.03.07 |
---|---|
[5] 페이지 처리 controller 동작 (0) | 2025.03.06 |
[3] DTO 설정 (0) | 2025.03.04 |
[2] Querydsl (0) | 2025.03.04 |
[1] Entity Test (0) | 2025.03.04 |