스프링 Pageable를 이용하면 페이징을 쉽게 구현할 수 있다.
@GetMapping
public ResponseEntity getMembers(@PageableDefault(sort = "memberId", direction = Sort.Direction.DESC) Pageable pageable) {
Page<Member> page = memberService.findMembers(pageable);
PageGetResponseDto response = mapper.pageToResponseDto(page);
return new ResponseEntity<>(response, HttpStatus.OK);
}
상기 코드는 /members에 Get 요청을 하면 실행된다.
Pageable을 통해 불러올 페이지, 한페이지에 몇개의 데이터를 보여주는 사이즈를 파라미터로 받아온다.
localhost:8080/v10/members?size=5&page=1
즉 위 주소는 5개씩 데이터를 가져오는데 1페이지를 보여주는 쿼리를 만들어준다.
public interface MemberRepository extends CrudRepository<Member, Long> {
Optional<Member> findByEmail(String email);
Page<Member> findAll(Pageable pageable);
}
jpa가 아닌 jdbc를 쓴 상황임... 원래 jpa를 자주 쓰는데 교육 받는다고 jdbc를 썼다.
엄밀히 말하면 스프링data jdbc인 상황임.
스프링data jpa에서도 잘 먹으니까 여기서도 뭐 잘 되겠지
public Page<Member> findMembers(Pageable pageable) {
return memberRepository.findAll(pageable);
}
서비스 클래스에서도 간단하게 작성해준다.
pageable page, size 즉 offset, limit가 다 잡혀 있으니까
이래 넘겨도 될 거임
public class PageGetResponseDto {
private List<Member> data;
private PageInfo pageInfo;
}
ResponseEntity에 빼기 편하게 하려고 Dto 클래스를 만들어준다.
data는 Page의 content를 가져갈가고 PageInfo는 페이지, 사이즈, 토탈데이터수, 토탈페이지를 가져갈거다.
public class PageInfo {
private int page;
private int size;
private int totalElements;
private int totalPages;
}
맵퍼 클래스를 써줘야 한다.
@Mapper(componentModel = "spring")
public interface MemberMapper {
Member memberPostDtoToMember(MemberPostDto memberPostDto);
Member memberPatchDtoToMember(MemberPatchDto memberPatchDto);
MemberResponseDto memberToMemberResponseDto(Member member);
List<MemberResponseDto> membersToMemberResponseDtos(List<Member> members);
default PageGetResponseDto pageToResponseDto(Page<Member> page) {
PageGetResponseDto pageGetResponseDto
= new PageGetResponseDto(
page.getContent(),
new PageInfo(page.getNumber() + 1, page.getSize(), page.getNumberOfElements(), page.getTotalPages())
);
return pageGetResponseDto;
}
}
아직 mapper 사용에 익숙치 않아서 그냥 디폴트로 선언해서 수동으로 만들어줬다.
쿼리도 잘 나가고 결과값도 만족스러움.
페이지에 -2도 넣어봤는데, 알아서 0으로 잡아줬다.
그리고 페이지는 0부터 시작이기 때문에 몇가지 옵션을 부여했다.
우선 pageInfo 맵핑땐 +1을 달아줬고, Pageable 내부 옵션을 바꿔줌
(@PageableDefault(sort = "memberId", direction = Sort.Direction.DESC) Pageable pageable)
memberId로 sort할건데, 방향이 내림차순이야 라고 선언해줬다.
이 외에도 size나 page도 조절 가능하니 참고
파라미터가 0으로 들어오고 0페이지가 보여서 헷갈리는 부분은
application.properties에서 옵션을 좀 넣어주면 된다.
yml방식
spring:
data:
web:
pageable:
one-indexed-parameters: true
이걸로 해결할 수 있다.
one-indexed-parameters를 true로 하면 1부터 셈.
물론 쿼리는 알아서 0으로 나가고, 상기 Page의 page필드도 0이니까 조절이 조금 필요하긴 하다.
# DATA WEB (SpringDataWebProperties)
spring.data.web.pageable.default-page-size=20 # Default page size.
spring.data.web.pageable.max-page-size=2000 # Maximum page size to be accepted.
spring.data.web.pageable.one-indexed-parameters=false # Whether to expose and assume 1-based page number indexes.
spring.data.web.pageable.page-parameter=page # Page index parameter name.
spring.data.web.pageable.prefix= # General prefix to be prepended to the page number and page size parameters.
spring.data.web.pageable.qualifier-delimiter=_ # Delimiter to be used between the qualifier and the actual page number and size properties.
spring.data.web.pageable.size-parameter=size # Page size parameter name.
spring.data.web.sort.sort-parameter=sort # Sort parameter name.
속성으로는 위와 같은 친구들이 있으니까 참고해서 잘 쓰자.
application.properties에서 설정하면 글로벌 옵션이 되니까 참고