4월 19일

오늘 배운 것

  • 페이징(1)

페이징(1)

DBMS프로그램의 종류에 따라 방식의 차이가 있음

Oracle

  • oracle의 경우에는 가상의 Column인 rownum을 만드는 방식으로 페이징을 만들 수 있다.
  • rownum은 select의 결과를 순번에 따라 각 행에 번호를 붙여주는 기능

방식 1. 모든 데이터를 검색 후 지정범위의 데이터만 선택

select * 
from(
        select rownum as rn, bno, title, content, writer, regdate, updatedate
        from board 
    )
where rn between 11 and 20

방식 2. 일부분의 데이터만 검색 한 후 추가적으로 범위지정

select * 
from(
        select  rownum  as rn, bno, title, content, writer, regdate, updatedate 
        from board where rn <= 20
    ) 
where rn > 11;

1의 방식보단 2의 방식이 실행속도면에서 빠르다.

MySql

  • limit 메소드를 사용하여 원하는 범위의 데이터만 출력
  • limit 숫자1, 숫자2 =>
    숫자1은 가장 맨위의 데이터 부터 skip할 행의 갯수
    숫자2는 skip이 끝난 행부터 출력할 행의 갯수
    예를 들어 limit 10, 10이면 10개의 행을 건너띄고 11번째행부터 10개의행, 즉 20번째 행까지 선택
        select * 
        from (
                select bno, title, writer, regdate, updatedate  
                from vam_board order by bno desc
             ) as T1 
        limit 숫자1, 숫자2

참고(rownum 기본)

https://wakestand.tistory.com/244


페이징적용하기

  • MySql을 사용하고 있기때문에 limit메소드를 사용
  • 페이지계산을 위한 Criteria클래스 생성
package com.myapp.bbs.model;

/**
 * 페이지 계산을 위한 클래스
 * 
 *
 */
public class Criteria {

	private int pageNum; // 현재 페이지
	
	private int amount; // 한 페이지당 보여질 게시글 수

	private int skip; // 스킵할 페이지 수 ((pageNum -1) * amount)
	
	public Criteria() { // 기본 생성자 -> 기본 세팅: pageNum = 1; amount = 10 
		this(1,10); // 전체 생성자를 통해 (1,10)을 입력해 객체 생성 -> Criteria(1,10)
	}
	
	public Criteria(int pageNum, int amount) {
		this.pageNum = pageNum;
		this.amount = amount;
		this.skip = (pageNum - 1) * amount;
	}

	public int getPageNum() {
		return pageNum;
	}

	// 새로 페이지 숫자를 설정 했을 때 skip도 같이 계산하여 입력
	public void setPageNum(int pageNum) {
		this.pageNum = pageNum;
		this.skip = (pageNum - 1) * amount;
	}

	public int getAmount() {
		return amount;
	}

	// 페이지당 보여질 게시글 수를 새로 설정 했을 때 skip도 같이 계산하여 입력
	public void setAmount(int amount) {
		this.amount = amount;
		this.skip = (pageNum - 1) * amount;
	}

	public int getSkip() {
		return skip;
	}

	public void setSkip(int skip) {
		this.skip = skip;
	}

	@Override
	public String toString() {
		return "Criteria [pageNum=" + pageNum + ", amount=" + amount + ", skip=" + skip + "]";
	}
}
  • 페이지네이션을 위한 PageMakerDTO클래스 생성
  • 실수를 사용하고 ceil(올림)을 해주는 이유는 페이지에 데이터를 출력하고 나머지 데이터가 있으면 무조건 다음 페이지를 만들기위해서
package com.myapp.bbs.model;

import lombok.Data;

/**
 * 페이지 네이션을 위해서 전체게시물 수와 cri를 입력받아 계산하여
 * 시작페이지, 끝페이지, 이전,다음페이지 유무를 저장
 * 
 *
 */
@Data
public class PageMakerDTO {
	
	// 시작 페이지(현재페이지)
	private int startPage;
	
	// 마지막 페이지
	private int endPage;
	
	// 이전페이지, 다음페이지 유무
	private boolean prev, next;
	
	// 전체 게시글 수
	private int total;
	
	// 현재 페이지, 페이지당 게시글 출력 수 정보
	private Criteria cri;

	public PageMakerDTO(int total, Criteria cri) {
		this.total = total;
		this.cri = cri;
		
		// 마지막 페이지 : 10 단위로 표시 1~10, 11~20, 21~30, ceil은 올림
		// 현재 페이지가 1이면 끝페이지는 10, 11이면 끝페이지는 20
		this.endPage = (int)(Math.ceil(cri.getPageNum()/10.0)) * 10;
		
		// 시작페이지
		this.startPage = this.endPage - 9;
		
		// 실제 마지막 페이지
		int realend = (int)(Math.ceil(total * 1.0/cri.getAmount()));
		
		// 실제 마지막 페이지(realend)가 화면에 보이는 마지막페이지(endPage)보다 작은경우, endPage값을 조정
		if(realend < this.endPage) {
			realend = this.endPage;
		}
		
		// < 이전페이지가 true이려면 시작 페이지(startPage)값이 1보다 큰 경우 true
		this.prev = this.startPage > 1;
		
		// > 다음페이지가 true이려면 마지막 페이지(endPage)값이 realend값보다 작은 경우 true
		this.next= this.endPage < realend;
	}
}
  • Mapper, Service에 입력
	// pageNum , amount를 입력받아 개체 cri생성, 없으면 기본 (1,10)입력
	public List<BoardVO> getListPaging(Criteria cri); // 게시판 모든 글 불러오기(페이징 적용)
    
    public int getTotal(); // 게시글 총 갯수
  • Controller의 모든 게시글 출력메소드 수정
  • @ModelAttribute 생략가능, 매개변수에 객체가 있으면 객체안의 변수는 자동으로 입력됨
	@GetMapping("/list")
	public String boardListGet(Criteria cri, Model model) {
		log.info("게시판 리스트 페이지 진입");
		model.addAttribute("boardList", boardService.getListPaging(cri));
		
		int total = boardService.getTotal();
		PageMakerDTO pmk = new PageMakerDTO(total, cri);
		model.addAttribute("pmk", pmk);
		
		return "list";
	}

페이지(1)

  • th:if로 pmk.endPage가 0보다 작으면 나타나지않도록 함
  • th:each 반복문으로 페이지 출력
            <!-- 페이지네이션-->
            <nav aria-label="Page navigation" th:if="${pmk.endPage > 0}">
              <ul class="pagination">
                <li class="page-item">
                  <a class="page-link" href="javascript:;" aria-label="이전">
                    <span class="material-icons">
                      keyboard_arrow_left
                    </span>
                    <span class="sr-only">Previous</span>
                  </a>
                </li>
                <li class="page-item" th:each="number : ${#numbers.sequence(1,pmk.endPage)}">
                  <a class="page-link" href="javascript:;" th:text="${number}"></a>
                </li>
                
                <li class="page-item">
                  <a class="page-link" href="javascript:;" aria-label="다음">
                    <span class="material-icons">
                      keyboard_arrow_right
                    </span>
                    <span class="sr-only">Next</span>
                  </a>
                </li>
              </ul>
            </nav>

좋은 웹페이지 즐겨찾기