[JPA] Pageable로 페이지 처리하기

Pageable로 페이지 처리하기

Pageable을 이용해 JPA에서 페이지 단위로 데이터를 받아보자.

TaskRepository

Task라는 모델을 받는 TaskRepository를 만들고, 페이지 단위로 Task를 받도록 해보자.

import com.vividswan.studymate.model.Task;
import org.springframework.data.jpa.repository.JpaRepository;

public interface TaskRepository extends JpaRepository<Task ,Long> {
}

우선 JpaRepositoryTask 타입과 Task의 PK 타입으로 제네릭 하여 상속받는 인터페이스를 작성하면, Task Entity에 대한 CRUD 메서드를 호출할 수 있는 TaskRepository가 만들어진다.

여기서 페이지 단위로 데이터를 받기 위한 코드를 추가하자.

package com.vividswan.studymate.repository;

import com.vividswan.studymate.model.Task;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;

public interface TaskRepository extends JpaRepository<Task ,Long> {
    Page<Task> findAllByUserIdAndIsSuccess(Long userId, int isSuccess, Pageable pageable);
}

findAllByUserIdAndIsSuccess

Task Table에서 userId라는 속성과 isSuccess라는 속성을 입력받아 조회할 수 있는 메서드를 만들었다.

Page

return 값은 페이지 단위의 Task 타입이다.

메서드 파라미터

Long userId, int isSuccess, Pageable pageable

메서드에 들어가는 파라미터를 확인해보자.
userId 속성과 isSuccess 속성을 바탕으로 조회를 하기 때문에 이 두 값을 파라미터에 넣어줘야 한다.
그 뒤에 가장 중요한 Page에 대한 설정값을 담아 줄 Pageable pageable 을 파라미터로 넣어줘야 페이지 처리를 할 수 있다.

TaskService

package com.vividswan.studymate.service;

import com.vividswan.studymate.config.auth.PrincipalDetails;
import com.vividswan.studymate.model.Task;
import com.vividswan.studymate.repository.TaskRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


@Service
@RequiredArgsConstructor
public class TaskService2 {

    private final TaskRepository taskRepository;


    @Transactional(readOnly = true)
    public Page<Task> findList(PrincipalDetails principalDetails, @PageableDefault(size=8, sort = "deadline", direction = Sort.Direction.ASC) Pageable pageable) {
        return taskRepository.findAllByUserIdAndIsSuccess(principalDetails.getUserId(),0, pageable);
    }

}

다음과 같이 Service 계층에서 페이지 단위로 Task 객체를 불러올 수 있는 findList 메서드를 만들어주자.

@Transactional(readOnly = true)

삽입, 수정, 삭제가 아닌 조회만 하는 메서드이므로 readOnly 트랜잭션을 선언해 준다.

PrincipalDetails principalDetails

UserId를 출력하기 위해 선언했다.
spring security context holder에 있는 세션 값을 통해 userId를 불러온다.

@PageableDefault

@PageableDefault(size=8, sort = “deadline”, direction = Sort.Direction.ASC) Pageable pageable

@PageableDefault 어노테이션을 선언해 주고 page에 대한 설정을 할 수 있다.

  • size : 한 페이지에 담을 모델의 수를 정할 수 있다.
  • sort : 정렬의 기준이 되는 속성을 정할 수 있다.
  • direction : 오름차순과 내림차순 중 기준을 선택한다.
  • Pageable pageable : PageableDefault 값을 갖고 있는 변수를 선언한다.

페이지 출력

    @GetMapping("/todolist/proceeding")
    @ResponseBody
    public Page<Task> taskView(Model model, @AuthenticationPrincipal PrincipalDetails principalDetails, @PageableDefault(size=8, sort = "deadline", direction = Sort.Direction.ASC) Pageable pageable, int page){
        Page<Task> pagingTasks = taskService.findList(principalDetails, pageable);
        return pagingTasks;
    }

컨트롤러에서 @ResponseBody를 통해 데이터를 JSON 형태로 받아서 확인해보자.

결과

{
  "content": [
    {
      "id": 3,
      "title": "1234",
      "content": "<p>12345</p>",
      "createDate": "2020-10-13T15:31:32.965",
      "deadline": "2020-10-07T15:31:00",
      "user": {
        "id": 1,
        "username": "vividswan",
        "nickname": "수환",
        "email": "vividswan@naver.com",
        "password": "$2a$10$V.vNh2.zATNZqTeINZD57eGm6LD4C1ZxBJVah12MVZ6FBs1/tvKki",
        "role": "USER",
        "createDate": "2020-10-13T14:27:09.054"
      },
      "feedbacks": [
        
      ],
      "isSuccess": 0,
      "stringDeadline": "2020/10/07 03:31"
    }
  ],
  "pageable": {
    "sort": {
      "sorted": true,
      "unsorted": false,
      "empty": false
    },
    "pageNumber": 0,
    "pageSize": 8,
    "offset": 0,
    "paged": true,
    "unpaged": false
  },
  "totalPages": 1,
  "totalElements": 1,
  "last": true,
  "numberOfElements": 1,
  "first": true,
  "size": 8,
  "number": 0,
  "sort": {
    "sorted": true,
    "unsorted": false,
    "empty": false
  },
  "empty": false
}

위와 같이 페이지 처리되어 결과가 나옴을 확인할 수 있다.
JSON에 포함된 last, first, pageNumber, pageSize 등의 데이터를 화면을 구현할 때 활용할 수 있다.