/**
* 페이지네이션
* @param <T>
*/
@Getter @Setter @ToString
public class Pagination<T> {
private int page; // 현재 페이지
private long total; // 전체 레코드 수
private int prev; // 전 구간 마지막 페이지
private int next; // 다음 구간 마지막 페이지
private int lastPage; // 마지막 페이지
private int pageCnt; // 구간별 페이지 갯수
private int pagePerCnt; // 1 페이지당 레코드 수
private boolean isFirstCnt; // 첫 번째 구간 여부
private boolean isLastCnt; // 마지막 구간 여부
private List<Integer> pages; // 구간별 페이지 번호
private String baseUrl;
public Pagination(Page<T> data, String url) {
this(data.getNumber() + 1, data.getTotalElements(), data.getSize(), url);
}
public Pagination(int page, long total, String url) {
this(page, total, 20, url);
}
public Pagination(int _page, long _total, int _pagePerCnt, String url) {
total = _total;
pagePerCnt = _pagePerCnt;
page = _page <= 0 ? 1 : page;
if (total < 1) {
return;
}
baseUrl = url;
baseUrl = baseUrl == null ? "" : baseUrl;
this.pageCnt = pageCnt < 1 ? 10 : pageCnt; // 페이지 구간이 0 이하 인 경우는 기본값 10 지정
this.lastPage = (int) Math.ceil(total / (double) this.pagePerCnt); // 마지막 페이지
page = page < 1 ? 1 : page; // 페이지가 0 이하 일 경우 1로 고정
if (page > this.lastPage) page = this.lastPage; // 페이지가 마지막 페이지보다 크다면 마지막 페이지로 고정
pages = new ArrayList<>();
/** 페이지 구간 구하기 S */
int cnt = (int) Math.ceil(this.page / (double) this.pageCnt) - 1; // 현재 페이지 구간 번호
int lastCnt = (int) Math.ceil(this.lastPage / (double) this.pageCnt) - 1; // 마지막 페이지 구간 번호
if (cnt == 0) this.isFirstCnt = true; // 첫번째 페이지 구간 체크
if (cnt == lastCnt) this.isLastCnt = true; // 마지막 페이지 구간 체크
/** 페이지 구간 구하기 E */
/** 구간별 페이지 번호 S */
int start = cnt * this.pageCnt + 1;
for (int i = start; i < start + this.pageCnt; i++) {
pages.add(i);
if (i == this.lastPage) { // 마지막 페이지에서 멈춤
break;
}
}
/** 구간별 페이지 번호 E */
/** 전 구간 마지막 페이지 S */
if (!this.isFirstCnt) {
prev = cnt * this.pageCnt;
}
/** 전 구간 마지막 페이지 E */
/** 다음 구간 시작 페이지 S */
if (!this.isLastCnt) {
next = (cnt + 1) * this.pageCnt + 1;
}
/** 다음 구간 시작 페이지 E */
}
}
Repository.java(예시)
public interface RentalBookRepository extends JpaRepository<RentalBook, String>, QuerydslPredicateExecutor<RentalBook> {
default Page<RentalBook> getBooks(BookSearch bookSearch) {
/** 페이징 처리 S */
int page = bookSearch.getPage();
page = page < 1 ? 1 : page;
int limit = bookSearch.getLimit();
limit = limit < 1 ? 20 : limit;
Pageable pageable = PageRequest.of(page - 1, limit);
/** 페이징 처리 E */
/** 검색 조건 처리 S */
BooleanBuilder builder = new BooleanBuilder();
QRentalBook rentalBook = QRentalBook.rentalBook;
String bookId = bookSearch.getBookId();
String sopt = bookSearch.getSopt();
String skey = bookSearch.getSkey();
String[] status = bookSearch.getStatus();
String[] rentalType = bookSearch.getRentalType();
if (bookId != null && !bookId.isBlank()) { // 도서ID
builder.and(rentalBook.bookId.contains(bookId));
}
if (sopt != null && !sopt.isBlank() && skey != null && !skey.isBlank()) {
BooleanBuilder orBuilder = new BooleanBuilder();
if (sopt.equals("bookNm")) { // 책이름
orBuilder.or(rentalBook.bookNm.contains(skey));
} else if (sopt.equals("author")) { // 저자
orBuilder.or(rentalBook.author.contains(skey));
} else if (sopt.equals("publisher")) { // 출판사
orBuilder.or(rentalBook.publisher.contains(skey));
} else {
orBuilder.andAnyOf(rentalBook.bookNm.contains(skey),
rentalBook.author.contains(skey),
rentalBook.publisher.contains(skey));
}
builder.and(orBuilder);
}
if (status != null && status.length > 0) { // 대여 상태 조회
List<RentalStatus> statuses = Arrays.stream(status).map(RentalStatus::valueOf).toList();
builder.and(rentalBook.status.in(statuses));
}
if (rentalType != null && rentalType.length > 0) { // 도서 종류
List<RentalType> rentalTypes = Arrays.stream(rentalType).map(RentalType::valueOf).toList();
builder.and(rentalBook.rentalType.in(rentalTypes));
}
/** 검색 조건 처리 E */
Page<RentalBook> data = findAll(builder, pageable);
return data;
}
}
ListService.java
@Service
@RequiredArgsConstructor
public class BookListService {
private final EntityManager em;
private final RentalBookRepository repository;
private Page<RentalBook> data;
public BookListService gets(BookSearch bookSearch) {
data = repository.getBooks(bookSearch);
return this;
}
public List<RentalBook> toList() {
List<RentalBook> books = data.getContent();
books.stream().forEach(em::detach); // 영속성 분리
return books;
}
public Page<RentalBook> getPage() {
return data;
}
}
pagination.java
Repository.java(예시)
ListService.java
Controller.java(예시)
pagination.html