Pagealbe 객체(인터페이스)
org.springframework.data.domain
페이징 처리에 필요한 정보들을 모아두는 곳
react - npm
# Material Page component 업그레이드
# 과거 v4 -> v5 변경 설치
npm i @mui/material @emotion/react @emotion/styled
# 소스에서 임포트 사용법 : <Pagination />
import Pagination from '@mui/material/Pagination';
객체 만들기
// TODO : 사용법 : Pageable pageable = PageRequest.of(현재페이지번호,1페이지당 개수);
Pageable pageable = PageRequest.of(page, size);
< 예제 >
< SpringBoot >
부서 - Repository
( Service 생략 )
@Repository
public interface DeptRepository extends JpaRepository<Dept , Integer> {
// TODO : Dname Like 검색 + 페이징 처리 (리턴 : Page , 매개변수 :Pageable)
Page<Dept> findAllByDnameContaining(String dname , Pageable pageable);
}
부서 - Controller
@RestController
@Slf4j
@RequestMapping("/api/basic")
public class DeptController {
@Autowired
DeptService deptService;
// 전체 조회 + dname like 검색
@GetMapping("/dept")
public ResponseEntity<Object> find(
@RequestParam(defaultValue = "") String dname,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "3") int size
){
try {
// 페이지 변수 저장 (page:현재페이지번호, size:1페이지당개수)
// 함수 매개변수 : Pageable (위의 값을 넣기)
// 사용법 : Pageable pageable = PageRequest.of(현재페이지번호, 1페이지당개수);
Pageable pageable = PageRequest.of(page, size);
// 전체조회(dname="") + like 검색(dname="S")
Page<Dept> deptPage
= deptService.findAllByDnameContaining(dname, pageable);
// 리액트 전송 : 부서배열 , 페이징정보 [자료구조 : Map<키이름, 값>]
Map<String , Object> response = new HashMap<>();
response.put("dept", deptPage.getContent()); // 부서배열
response.put("currentPage", deptPage.getNumber()); // 현재페이지번호
response.put("totalItems", deptPage.getTotalElements()); // 총건수(개수)
response.put("totalPages", deptPage.getTotalPages()); // 총페이지수
if (deptPage.isEmpty() == false) {
// 성공
return new ResponseEntity<>(response, HttpStatus.OK);
} else {
// 데이터 없음
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
}catch (Exception e) {
log.debug(e.getMessage());
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
< React >
인터페이스 - types
export default interface IDept {
dno?: any | null,
dname: string,
loc: string
}
Pagenation 사용 페이지
// DeptList.tsx : 전체 조회 페이지 + 페이징
import React, { useState } from "react";
import { Link } from "react-router-dom";
import TitleCom from "../../../components/common/TitleCom";
import { Pagination } from "@mui/material";
import IDept from "../../../types/basic/IDept";
import { useEffect } from "react";
import DeptService from "../../../services/basic/DeptService";
function DeptList() {
// 변수 정의
const [dept, setDept] = useState<Array<IDept>>([]); // 부서 배열
const [searchDname, setSearchDname] = useState<string>(""); // 검색어 변수
// TODO : 공통 변수(필수) : page(현재 페이지), count(총 페이지 건수) , pageSize(3,6,9 배열 : 1페이지 당 건수)
const [page, setPage] = useState<number>(1); // 현재 페이지 번호 : 최초값 1
const [count, setCount] = useState<number>(1); // 총페이지 건수 : 최초값 1
const [pageSize, setPageSize] = useState<number>(3); // 1페이지당 개수 : 최초값 3
const pageSizes = [3, 6, 9]; // selectBox 에 사용될 변수(선택)
// 함수 정의
// TODO : 1) 컴포넌트가 mounted 될때 한번만 실행됨 : useEffect(() => {},[])
// TODO : 2) 컴포넌트가의 변수값이 변할때 실행됨 : useEffect(() => {실행문},[감시변수])
useEffect(() => {
retrieveDept(); // 전체 조회 함수 실행
}, [page, pageSize]);
// TODO : 전체 조회 함수
const retrieveDept = () => {
// 백엔드 매개변수 전송 : + 현재페이지(page) , 1페이지당 개수(pageSize)
DeptService.getAll(searchDname, page - 1, pageSize)
.then((response: any) => {
// 백엔드 성공시 실행됨
// es6(모던js) 문법 : 객체 분해 할당
// const dept = response.data.dept; // 부서 배열
// const totalPages = response.data.totalPages; // 전체페이지수
const { dept, totalPages } = response.data;
// dept 저장
setDept(dept);
setCount(totalPages);
// 로그 출력
console.log("response", response);
})
.catch((e: Error) => {
// 백엔드 실패시 실행됨
console.log(e);
});
};
// TODO : Like 검색 창
const onChangeSearchDname = (e: React.ChangeEvent<HTMLInputElement>) => {
const searchDname = e.target.value;
setSearchDname(searchDname);
};
// TODO : pageSize 값 변경시 실행되는 함수 (select box)
// TODO : SELECT BOX 태그 수동 바인딩 : 화면값 -> 변수에 저장
const handlePageSizeChange = (event: any) => {
setPageSize(event.target.value); // 1페이지당 개수 저장(3,6,9)
setPage(1); // 현재 페이지번호 : 1로 강제 설정 (선택사항)
};
// TODO : Pagenation 수동 바인딩
// TODO : 페이지 번호를 누르면 -> page 변수에 값 저장
const handlePageChange = (event: any, value: number) => {
// value == 화면의 페이지번호
setPage(value);
};
return (
<div>
<>
{/* 제목 start */}
<TitleCom title="Dept List" />
{/* 제목 end */}
{/* dname start (검색어 입력창) */}
<div className="row mb-5 justify-content-center">
{/* w-50 : 크기 조정, mx-auto : 중앙정렬(margin: 0 auto), justify-content-center */}
<div className="col-12 w-50 input-group mb-3">
<input
type="text"
className="form-control"
placeholder="Search by dname"
value={searchDname}
onChange={onChangeSearchDname}
/>
<div className="input-group-append">
<button
className="btn btn-outline-secondary"
type="button"
onClick={retrieveDept}
>
Search
</button>
</div>
</div>
</div>
{/* dname end */}
{/* paging 시작 (페이지 번호 컴포넌트) */}
<div className="mt-3">
{"Items per Page: "}
{/* 페이지 size 변경하는 select 박스 */}
<select onChange={handlePageSizeChange} value={pageSize}>
{pageSizes.map((size) => (
<option key={size} value={size}>
{size}
</option>
))}
</select>
{/* Pagination : Material UI (구글에서 제공하는 컴포넌트) 시작 */}
{/* count : 총페이지 건수(개수) */}
{/* page : 현재페이지 번호 */}
<Pagination
className="my-3"
count={count}
page={page}
siblingCount={1}
boundaryCount={1}
variant="outlined"
shape="rounded"
onChange={handlePageChange}
/>
{/* Pagination : Material UI (구글에서 제공하는 컴포넌트) 끝 */}
</div>
{/* paging 끝 */}
{/* table start */}
<div className="col-md-12">
table start
<table className="table">
<thead className="table-light">
<tr>
<th scope="col">Dno</th>
<th scope="col">Dname</th>
<th scope="col">Loc</th>
<th scope="col">Update</th>
</tr>
</thead>
<tbody>
{dept &&
dept.map((data) => (
<tr key={data.dno}>
<td>{data.dno}</td>
<td>{data.dname}</td>
<td>{data.loc}</td>
<td>
<Link to={"/dept/" + data.dno}>
<span className="badge bg-success">Edit</span>
</Link>
</td>
</tr>
))}
</tbody>
</table>
{/* table end */}
</div>
{/* table end */}
</>
</div>
);
}
export default DeptList;
React - service
// TODO : AXIOS 공통 함수 : 백엔드 연동
import IDept from "../../types/basic/IDept";
import http from "../../utils/http-common";
// 전체 조회 + LIKE 검색(PAGING 기능 : page(현재페이지) , size(1페이지당 개수))
const getAll = (dname:any, page:number, size:number) => {
return http.get<Array<IDept>>(`/basic/dept?dname=${dname}&page=${page}&size=${size}`);
};
const DeptService = {
getAll
};
export default DeptService;
'SpringBoot > JPA' 카테고리의 다른 글
SpringBoot - JPA - @Query insert 문 (0) | 2023.10.27 |
---|---|
SpringBoot - CSR 과 연동 시 주의점 (CORS) 설정 (0) | 2023.10.19 |
SpringBoot - Hard Delete 와 Soft Delete 개념 (0) | 2023.10.19 |
SpringBoot - JPA - 1 대 1 관계 (0) | 2023.10.19 |
SpringBoot - JPA - 조인 ( 1 대 다 관계 ) (0) | 2023.10.19 |