Spring Data jpa 페이징 (2)

zwon·2023년 10월 10일
0

Spring

목록 보기
12/12

Spring Data Jpa에서 페이징과 정렬기능을 스프링 MVC에서 편하게 사용할 수 있다.

바로 코드를 봐보자.


Controller

@RestController
@RequiredArgsConstructor
public class MemberController {
  private final MemberRepository memberRepository;
  
  @GetMapping("/members")
  public Page<Member> memberList(Pageable pageable){
    Page<Member> page = memberRepository.findAll(pageable);
    return page;
  }
  
  @PostConstruct
  public void init() {
    for(int i = 0; i<100; i++){
      memberRepository.save(new Member("user"+i));
    }
  }
}
  • memberList 메서드의 파리미터로 Pageable이 날라온다.
  • pageable은 인터페이스여서 구현체로 PageRequest를 사용한다.
protected PageRequest(int page, int size, Sort sort) {
	super(page, size);
	Assert.notNull(sort, "Sort must not be null");
	this.sort = sort;
}
public static PageRequest of(int page, int size) {
	eturn of(page, size, Sort.unsorted());
}

public static PageRequest of(int page, int size, Sort sort) {
	return new PageRequest(page, size, sort);
}

public static PageRequest of(int page, int size, Direction direction, String... properties) {
	return of(page, size, Sort.by(direction, properties));
}
  • PageRequest를 생성할 때 생성자를 통해 객체를 생성하는 것은 deprecated되어 있다고 한다. 그래서 정적 팩토리 메서드 패턴으로 PageRequest.of(...)로 PageRequest를 생성한다.
  • 다시 본론으로 돌아가자면 파라미터로 Pageable을 받아 Web의 요청 파라미터를 Pageable과 바인딩할 수 있다.
  • 정리하자면 컨트롤러에서 파라미터로 Pageable이 있으면 스프링 부트가 PageRequest객체를 생성해서 파라미터로 넘어온 값들을 바인딩 해준다.

이렇게 작성하면 끝이다.
postman을 통해 페이징 파라미터를 함께 전달해보자

요청 파라미터

  • page : 현재 페이지, 0부터 시작
  • size : 한 페이지에 노출할 데이터 건수
  • sort : 정렬 조건

요청 파라미터 page

GET - http://localhost:8080/members?page=0

결과

{
    "content": [
        {
            "createdDate": "2023-10-10T12:42:35.991973",
            "updatedDate": "2023-10-10T12:42:35.991973",
            "id": 1,
            "username": "user0",
            "age": 0,
            "team": null
        },
        {
            "createdDate": "2023-10-10T12:42:36.021407",
            "updatedDate": "2023-10-10T12:42:36.021407",
            "id": 2,
            "username": "user1",
            "age": 1,
            "team": null
        },
      
        ...
     
        {
            "createdDate": "2023-10-10T12:42:36.06707",
            "updatedDate": "2023-10-10T12:42:36.06707",
            "id": 18,
            "username": "user17",
            "age": 17,
            "team": null
        },
        {
            "createdDate": "2023-10-10T12:42:36.068257",
            "updatedDate": "2023-10-10T12:42:36.068257",
            "id": 19,
            "username": "user18",
            "age": 18,
            "team": null
        },
        {
            "createdDate": "2023-10-10T12:42:36.069959",
            "updatedDate": "2023-10-10T12:42:36.069959",
            "id": 20,
            "username": "user19",
            "age": 19,
            "team": null
        }
    ],
    "pageable": {
        "sort": {
            "empty": true,
            "unsorted": true,
            "sorted": false
        },
        "offset": 0,
        "pageNumber": 0,
        "pageSize": 20,
        "paged": true,
        "unpaged": false
    },
    "last": false,
    "totalElements": 100,
    "totalPages": 5,
    "number": 0,
    "first": true,
    "sort": {
        "empty": true,
        "unsorted": true,
        "sorted": false
    },
    "size": 20,
    "numberOfElements": 20,
    "empty": false
}
  • 결과를 보니 디폴트가 20개인가보다. 20개가 불러와졌다.

요청 파라미터 page & size

GET - http://localhost:8080/members?page=0&size=3

결과

{
    "content": [
        {
            "createdDate": "2023-10-10T12:42:35.991973",
            "updatedDate": "2023-10-10T12:42:35.991973",
            "id": 1,
            "username": "user0",
            "age": 0,
            "team": null
        },
        {
            "createdDate": "2023-10-10T12:42:36.021407",
            "updatedDate": "2023-10-10T12:42:36.021407",
            "id": 2,
            "username": "user1",
            "age": 1,
            "team": null
        }
    ],
    "pageable": {
        "sort": {
            "empty": true,
            "unsorted": true,
            "sorted": false
        },
        "offset": 0,
        "pageNumber": 0,
        "pageSize": 2,
        "paged": true,
        "unpaged": false
    },
    "last": false,
    "totalElements": 100,
    "totalPages": 50,
    "number": 0,
    "first": true,
    "sort": {
        "empty": true,
        "unsorted": true,
        "sorted": false
    },
    "size": 2,
    "numberOfElements": 2,
    "empty": false
}
  • page파라미터를 1로 바꾸면 2번째 페이지로 , 3과 4를 가져온다. 3으로 바꾸면 5와6을 가져올 것이다
{
    "content": [
        {
            "createdDate": "2023-10-10T12:42:36.025348",
            "updatedDate": "2023-10-10T12:42:36.025348",
            "id": 3,
            "username": "user2",
            "age": 2,
            "team": null
        },
        {
            "createdDate": "2023-10-10T12:42:36.04167",
            "updatedDate": "2023-10-10T12:42:36.04167",
            "id": 4,
            "username": "user3",
            "age": 3,
            "team": null
        }
    ],
    "pageable": {
        "sort": {
            "empty": true,
            "unsorted": true,
            "sorted": false
        },
        "offset": 2,
        "pageNumber": 1,
        "pageSize": 2,
        "paged": true,
        "unpaged": false
    },
    "last": false,
    "totalElements": 100,
    "totalPages": 50,
    "number": 1,
    "first": false,
    "sort": {
        "empty": true,
        "unsorted": true,
        "sorted": false
    },
    "size": 2,
    "numberOfElements": 2,
    "empty": false
}

sort를 추가해보자
오름차순은 결과과 위와 똑같아서 내림차순으로 했다.

요청 파라미터 page & size & sort

GET - http://localhost:8080/members?page=0&size=2&sort=id,desc

결과

{
    "content": [
        {
            "createdDate": "2023-10-10T12:42:36.15968",
            "updatedDate": "2023-10-10T12:42:36.15968",
            "id": 100,
            "username": "user99",
            "age": 99,
            "team": null
        },
        {
            "createdDate": "2023-10-10T12:42:36.158977",
            "updatedDate": "2023-10-10T12:42:36.158977",
            "id": 99,
            "username": "user98",
            "age": 98,
            "team": null
        }
    ],
    "pageable": {
        "sort": {
            "empty": false,
            "unsorted": false,
            "sorted": true
        },
        "offset": 0,
        "pageNumber": 0,
        "pageSize": 2,
        "paged": true,
        "unpaged": false
    },
    "last": false,
    "totalElements": 100,
    "totalPages": 50,
    "number": 0,
    "first": true,
    "sort": {
        "empty": false,
        "unsorted": false,
        "sorted": true
    },
    "size": 2,
    "numberOfElements": 2,
    "empty": false
}

DTO 변환

API 요청 결고값으로 엔티티를 그대로 노출시키는 것보다 DTO로 변환해서 노출시켜야한다.
Page는 map()지원해서 쉽게 DTO로 변환할 수 있다.

@GetMapping("/members") 
public Page<MemberDto> list(Pageable pageable) { 
    Page<Member> page = memberRepository.findAll(pageable);
    Page<MemberDto> pageDto = page.map(MemberDto::new);
    return pageDto;
}

인프런 - (실전! 스프링 데이터 JPA)[https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%8D%B0%EC%9D%B4%ED%84%B0-JPA-%EC%8B%A4%EC%A0%84/dashboard]를 수강하면서 정리한 글입니다.

profile
Backend 관련 지식을 정리하는 Back과사전

0개의 댓글