BoardImpl 에 모든 걸 다 넣어도 되겠지만 그러고 싶지 않았다. (마음이 불편함) 그래서 Pagination 이라는 클래스와 BoardPagingDTO 를 추가했다. 앞단에서 list 랑 pagination 을 받듯이 뒷단에서 list, pagination 을 보내줘야 하는데 기존에 만들었던 BoardFileDTO 로는 보낼 수 없다.
물론 필드를 추가하면 되겠지만.. 이름이 BoardFileDTO 인데..? (마음이 불편함) 그래서 추가했고 처음에는 Pagination 으로 다 할 생각이었는데 DTO 를 추가하니까 둘의 역할이 겹친다. 나중에 시간 남으면 합치든가 해야지...(시간 없을 예정임)
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Pagination {
private static final int DISPLAY_PAGES = 3;
private int current_page;
private int start_page;
private int end_page;
private int total_pages;
private int page_size = 5; // 기본 페이지 크기
private String sort_by;
private String order;
private int start_row;
private int end_row;
public void setCurrent_page(int current_page) {
this.current_page = current_page;
calculateRows();
calculatePages();
}
public void setSort_by(String sort_by) {
if (sort_by == null || sort_by.trim().isEmpty()) {
this.sort_by = "bno"; // 기본값 설정
} else {
this.sort_by = sort_by;
}
}
public void setOrder(String order) {
if (order == null || (!order.equalsIgnoreCase("asc") && !order.equalsIgnoreCase("desc"))) {
this.order = "asc"; // 기본값 설정
} else {
this.order = order.toLowerCase();
}
}
private void calculateRows() {
this.start_row = (this.current_page - 1) * this.page_size + 1;
this.end_row = this.current_page * this.page_size;
}
private void calculatePages() {
this.start_page = ((current_page - 1) / DISPLAY_PAGES) * DISPLAY_PAGES + 1;
this.end_page = Math.min(start_page + DISPLAY_PAGES - 1, total_pages);
}
public void setTotalPages(int totalCount) {
this.total_pages = (int) Math.ceil((double) totalCount / this.page_size);
}
}
그렇다 ... 딱히 할 말이 없다. start_row, end_row 는 몇 행부터 가져올 건지를 뜻하고 start_page end_page 는 말 그대로 페이지 번호다. 로직이 간단해서 할 말이 없을 줄 알았는데..... 있다.
public void setSort_by(String sort_by) { if (sort_by == null || sort_by.trim().isEmpty()) { this.sort_by = "bno"; // 기본값 설정 } else { this.sort_by = sort_by; } } public void setOrder(String order) { if (order == null || (!order.equalsIgnoreCase("asc") && !order.equalsIgnoreCase("desc"))) { this.order = "asc"; // 기본값 설정 } else { this.order = order.toLowerCase(); } }
쿼리를 보면 알겠지만 동적으로 컬럼을 줘버려서 없으면 무조건 에러가 난다. 당연히 빈문자열로 주면 에러남, 줬는데 안 줬대서 유효성 검사 추가했다. 검사도 아니고 그냥 default 값을 정해놓는 거라고 생각하면 된다. 흠 근데 애초에 정말 default 로 정할 수 있다던데 다음에 시간 나면ㅋㅋ 고쳐야지ㅋㅋ
@Select("SELECT * FROM ( " +
" SELECT a.*, ROWNUM rnum " +
" FROM ( " +
" SELECT * " +
" FROM board " +
" ORDER BY ${sort_by} ${order} " +
" ) a " +
" WHERE ROWNUM <= #{end_row} " +
") WHERE rnum >= #{start_row}")
public List<BoardFileDTO> getBoardList(Pagination pagination);
어노테이션 이제 다신 안 쓰기로 했다. 쿼리가 너무 짜증나게 생겼다 "" 와 + ... 에휴... xml 으로 해야지 꼭...아 그리고 오라클은 limit 이 없어서 ROWNUM 을 썼다. 오라클도 뭐 offset 이 생겼다던데 내가 하니까 안되던데... 내가 문제인듯?
페이징은 참고할 코드도 있고 자료도 1000000개라서 하는데 하루도 안 걸렸다. 할 때는 재미 없었는데 다 하고나니까 너무 재밌다ㅋㅋ