SpringBoot 에서 JPA로 페이징처리를 해보자
스프링부트에서 JPA를 사용하여 간단한 페이징 처리를 해보자.
페이징 처리를 해볼 예시 Player 테이블의 구조는 다음과 같습니다.
PLAYER_ID | PLAYER_NAME | SEASON_ID |
(PK)INTEGER | VARCHAR | INTEGER |
사용자에게서 선수이름을 입력받으면 입력받은 문자가 포함되어있는 모든 선수의 아이디와 이름을 조회할 것이고 페이지에 모두 보여줄 것입니다.
PlayerRepository
public interface PlayerRepository extends JpaRepository<Player, Integer>
{
List<Player> findByPlayerNameContaining(String name);
}
이 때 사용자가 입력한 문자가 포함된 선수가 너무 많으면..?
제임스, 다비드 같은 흔한 이름 or 성이라면 백명 단위로 보여질 수가 있습니다.
따라서 페이징 처리가 필요합니다.
목표
사용자가 선수 검색할 때 조회 결과를 한 페이지에 5명씩 나타내고
Thymeleaf를 통해 간단한 페이지네이션을 해보자!
PlayerRepository
import org.springframework.data.domain.*;
public interface PlayerRepository extends JpaRepository<Player, Integer>
{
Page<Player> findByPlayerNameContaining(String name, Pageable pageable);
}
PlayerService
@Service
@RequiredArgsConstructor
public class PlayerService {
public Page<Player> getPlayerList(String playerName, Pageable pageable){
Page<Player> playerList =
playerRepository.findByPlayerNameContaining(playerName,pageable);
return playerList;
}
}
PlayerController
Thymeleaf 활용
@Controller
@RequiredArgsConstructor
public class PlayerController {
private final PlayerService playerService;
@GetMapping("/playersearch")
public String getPlayerList(
Model model , @RequestParam String pname,
@PageableDefault(size=5) Pageable pageable)
{
Page<Player> playerList = playerService.getPlayerList(pname,pageable);
model.addAttribute("playerlist",playerList.getContent());
model.addAttribute("next",playerList.hasNext());
model.addAttribute("current",playerList.getNumber());
model.addAttribute("url","/playersearch?pname="+pname+"&page=");
return "playersearch";
}
}
@PageableDefault의 옵션
page - 현재 페이지. 기본 0
size - 한 페이지에 나타낼 데이터 개수
sort - 정렬 기준으로 할 컬럼
direction - 정렬 방향
Page 클래스의 인터페이스
List
getContent() - 현재 페이지에 조회된 데이터
boolean hasContent() - 조회 데이터 존재 여부
int getNumber() - 현재 페이지
int getSize() - 페이지 크기
int getTotalPages() - 전체 페이지 수
long getTotalElements() - 전체 데이터 수
boolean hasPrevious() - 이전 페이지 존재 여부
boolean hasNextPage() - 다음 페이지 존재 여부
Pageable nextPageable() - 다음 페이지 객체, 없으면 null
Pageable previousPageable() - 다음 페이지 객체, 없으면 null
usersearch.html
컨트롤러로부터 전달받은 데이터를 뷰에 나타내고 간단한 이전페이지,다음페이지 구현
<body>
<div style="text-align: center">
<p th:text="|현재페이지 : ${current}|"></p>
</div>
<div style="text-align: center" th:each="p:${playerlist}">
<p th:text="|${p.playerId} - ${p.playerName}|"></p>
</div>
<div style="text-align: center">
<a th:if="${current}!=0" th:href="|${url}${current-1}|">뒤로</a>
<a th:if="${next}" th:href="|${url}${current+1}|">앞으로</a>
</div>
</body>
결과
‘토니’ 를 예시로 검색해보겠습니다.
페이지당 5개의 데이터가 출력됩니다.
토니가 들어간 선수가 이렇게나 많았군요
정렬을 활용하면 훨씬 깔끔하게 사용자가 조회결과를 볼 수 있겠네요.
저 같은 경우는 실제로 구현할 때 선수 기준포지션 오버롤(스탯) 내림차순이나 랭커들이 많이 사용하는 순서대로 정렬을 해볼까합니다.