기록하는 코더

[Spring] 페이징 처리 본문

JAVA/spring

[Spring] 페이징 처리

damda_di 2023. 2. 9. 15:54

EmpController.java

@GetMapping("/list")
public void list(@RequestParam Map<String, String> map,
                 @RequestParam(value="currentPage", required=false, defaultValue="1") int currentPage,
                 @RequestParam(value="show", required=false, defaultValue="10") int size
                 ,Model model) {
    // map으로 파라미터를 받아서 매퍼 xml에서 검색 조건으로 사용
    log.info("map : " + map);
    log.info("currentPage : " + currentPage);
    log.info("size : " + size);

    map.put("currentPage",currentPage+"");
    map.put("size",size+"");


    //map으로 파라미터를 받아서 매퍼xml에서 검색 조건으로 사용
    List<EmpVO> empVOList = this.empService.list(map);
    log.info("empVOList : " + empVOList);

    // total
    int total = this.empService.getTotal(map);
    log.info("total : " + total);


    // size <- map.get("show")
//		int size = Integer.parseInt(map.get("show"));



    // empVOList 객체를 페이징 처리해보자
    // new ArticlePage<EmpVO>(total, currentPage, content, size)
    model.addAttribute("data", new ArticlePage<EmpVO>(total, currentPage, empVOList, size));
    model.addAttribute("size", size);
}

 

emp_SQL.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.or.ddit.mapper.EmpMapper">
	<sql id="where">
		<!-- 조건 검색 -->
		<if test="keyword != null and keyword != ''">
			AND
			 (  T.EMP_NUM 	LIKE '%' || #{keyword} || '%' 
			 OR T.EMP_NM 	LIKE '%' || #{keyword} || '%' 
			 OR T.EMP_MJ_NM LIKE '%' || #{keyword} || '%'
			 )
		</if>
	</sql>
    
    <!-- 직원 목록
	들어오는 데이터 : map{show=10, keyword=핑구} 
	LIKE와 함께 사용한 퍼센트(여러 글자), 언더바(한 글자)를 와일드 카드라고 함
	-->
	<select id="list" resultType="empVO" parameterType="hashMap">
		SELECT * 
		FROM
		(
		WITH T AS (  
		    SELECT A.EMP_NUM, A.EMP_ADDR, A.EMP_PHE, A.EMP_NM, A.EMP_PAY,
		    A.EMP_MJ_NUM ,
		    (SELECT B.EMP_NM FROM EMP B WHERE B.EMP_NUM = A.EMP_MJ_NUM) EMP_MJ_NM
		      FROM EMP A
		      START WITH A.EMP_MJ_NUM IS NULL
		      CONNECT BY PRIOR A.EMP_NUM = A.EMP_MJ_NUM
		    )
		    SELECT ROWNUM RNUM
		        , T.EMP_NUM, T.EMP_ADDR, T.EMP_PHE, T.EMP_NM, T.EMP_PAY
		        , T.EMP_MJ_NUM, T.EMP_MJ_NM
		    FROM T
		    WHERE 1=1
		<include refid="where" />
		) U
		WHERE U.RNUM BETWEEN ((#{currentPage}*#{size})- (#{size}-1)) AND (#{currentPage}*#{size})
	</select>
	
	<!-- 목록의 행 수를 구함
		map {show:10, keyword:핑구, currentPage:1}
	 -->
	<select id="getTotal" resultType="int" parameterType="hashMap">
       WITH T AS(
           SELECT A.EMP_NUM, A.EMP_ADDR, A.EMP_PHE, A.EMP_NM, A.EMP_PAY
                , A.EMP_MJ_NUM
                , (SELECT B.EMP_NM FROM EMP B WHERE B.EMP_NUM = A.EMP_MJ_NUM) EMP_MJ_NM
           FROM   EMP A
           START WITH A.EMP_MJ_NUM IS NULL
           CONNECT BY PRIOR A.EMP_NUM = A.EMP_MJ_NUM
       )
       SELECT COUNT(*) TOTAL
       FROM   T
       WHERE  1 = 1
       <include refid="where"></include>
   </select>
   </mapper>

 

ArticlePage.java

더보기

 

package kr.or.ddit.util;

import java.util.List;

import kr.or.ddit.vo.LprodVO;

// 페이징 관련 정보 + 게시글 데이터
public class ArticlePage<T> {
	// 전체글 수 
	private int total;
	// 현재 페이지 번호
	private int currentPage;
	
	// ------ 계산이 필요한 부분
	// 전체 페이지 수
	private int totalPages;
	// 시작 페이지 번호
	private int startPage;
	// 종료 페이지 번호
	private int endPage;
	// ------ 계산이 필요한 부분
	
	// 블록 크기
	private int blockSize;
	
	// 글 데이터
	private List<T> content;
	// 생성자(Constructor) : 페이징 정보를 생성 및 초기화
	// size : 한 화면에 보여질 행의 수
	public ArticlePage(int total, int currentPage, List<T> content, int size) {
		this.total = total;
		this.currentPage = currentPage;
		this.content = content;
		
		if(total == 0) { // 전체 글 수가 0일 때
			totalPages = 0;
			startPage = 0;
			endPage = 0;
		}else { // 전체 글 수가 1 이상일 때
			// 1) 전체 페이지 구하기 시작 ----------------------
			// 전체 페이지 수 = 전체글 수  / 한 화면에 보여질 목록의 행 수 
			totalPages = total / size;
//			totalPages = (int) (Math.ceil(total / size));

			// 전체글 수 % 한 화면에 보여질 목록의 행 수
			// => 0 이 아니면 (나머지가 있다면) => 페이지를 1 증가
			if(total % size > 0) {
				totalPages++;
			}
			// 1) 전체 페이지 구하기 끝 ----------------------
			
			// 2) 시작 페이지 구하기 시작 ----------------------
			// 시작 페이지 = 현재 페이지 / 페이지크기 * 페이지크기 + 1
			// ex) 	startPage = 1 / 5 * 5 + 1
			//		startPage = (0.2 => 몫이 0) * 5 + 1
			//		startPage = 0 * 5 + 1
			//				  = 1
					
			// 1 set : 	  [1][2][3][4][5] 다음
			// 2 set : 이전 [6][7][8][9][10] 다음
			// 3 set : 이전 [11][12]
			
			startPage = currentPage / size * size + 1;
			
			// 현재페이지 % 페이지크기 => 0일때 보정
			if(currentPage % size == 0) {
				// 페이지 크기를 빼줌
				startPage -= size;
			}
			// 2) 시작 페이지 구하기 끝 ----------------------
			
			// 3) 종료 페이지 구하기 시작 ----------------------
			// 종료페이지 번호 = 시작페이지 번호 + (페이지크기 - 1)
			endPage = startPage + (size - 1);
			
			// 종료페이지번호 > 전체페이지수보다 클 때 보정
			if(endPage > totalPages) {
				endPage = totalPages;
			}
			// 3) 종료 페이지 구하기 끝 ----------------------
			
		}
	} // end AriclePage 생성자
	
	
	public int getTotal() {
		return total;
	}
	public void setTotal(int total) {
		this.total = total;
	}
	public int getCurrentPage() {
		return currentPage;
	}
	public void setCurrentPage(int currentPage) {
		this.currentPage = currentPage;
	}
	public int getTotalPages() {
		return totalPages;
	}
	public void setTotalPages(int totalPages) {
		this.totalPages = totalPages;
	}
	public int getStartPage() {
		return startPage;
	}
	public void setStartPage(int startPage) {
		this.startPage = startPage;
	}
	public int getEndPage() {
		return endPage;
	}
	public void setEndPage(int endPage) {
		this.endPage = endPage;
	}
	public int getBlockSize() {
		return blockSize;
	}
	public void setBlockSize(int blockSize) {
		this.blockSize = blockSize;
	}
	public List<T> getContent() {
		return content;
	}
	public void setContent(List<T> content) {
		this.content = content;
	}
	
	// 데이터가 없는 경우 => 전체 글의 수 0
	public boolean hasNoArticles() {
		return total == 0;
	}
	
	// 데이터가 있는 경우
	public boolean hasArticles() {
		return total > 0;
	}
}

 

 

list.jsp

<div class="card-body">
    <div class="table-responsive">
        <div id="dataTable_wrapper" class="dataTables_wrapper dt-bootstrap4">
        <!-- 검색영역 시작 
            action을 생략하면 현재의 URI, method를 생략하면 기본이 get -->
        <form name="frm" id="frm" action="/emp/list" method="get">
            <div class="row">
                <div class="col-sm-12 col-md-6">
                    <div class="dataTables_length" id="dataTable_length">
                        <label>Show 
                        <!-- 한 화면에 보여질 행의 수 -->
                        <select name="show" id="show"
                            aria-controls="dataTable"
                            class="custom-select custom-select-sm form-control form-control-sm"><option
                                    value="10">10</option>
                                <option value="25">25</option>
                                <option value="50">50</option>
                                <option value="100">100</option></select> entries
                        </label>
                    </div>
                </div>
                <div class="col-sm-12 col-md-6">
                    <div id="dataTable_filter" class="dataTables_filter">
                        <label>Search:<input type="search" name="keyword"
                            class="form-control form-control-sm" placeholder="검색어를 입력해주세요"
                            aria-controls="dataTable" value="${param.keyword}">
                            </label>
                        <label>
                            <button type="submit" class="btn btn-primary btn-icon-split btn-sm">
                                <span class="icon text-white-50">
                                    <i class="fas fa-flag"></i>
                                </span>
                                <span class="text">검색</span>
                            </button>							
                        </label>
                    </div>
                </div>
            </div>
            </form>
        <!-- 검색영역 끝 -->
            <div class="row">
                <div class="col-sm-12">
                    <table class="table table-bordered dataTable" id="dataTable"
                        width="100%" cellspacing="0" role="grid"
                        aria-describedby="dataTable_info" style="width: 100%;">
                        <thead>
                            <tr role="row">
                                <th class="sorting sorting_asc" tabindex="0"
                                    aria-controls="dataTable" rowspan="1" colspan="1"
                                    aria-sort="ascending"
                                    aria-label="Name: activate to sort column descending"
                                    style="width: 60.5px;">순번</th>
                                <th class="sorting" tabindex="0" aria-controls="dataTable"
                                    rowspan="1" colspan="1"
                                    aria-label="Position: activate to sort column ascending"
                                    style="width: 67.5px;">직원번호</th>
                                <th class="sorting" tabindex="0" aria-controls="dataTable"
                                    rowspan="1" colspan="1"
                                    aria-label="Office: activate to sort column ascending"
                                    style="width: 51.5px;">직원명</th>
                                <th class="sorting" tabindex="0" aria-controls="dataTable"
                                    rowspan="1" colspan="1"
                                    aria-label="Age: activate to sort column ascending"
                                    style="width: 30.5px;">급여</th>
                                <th class="sorting" tabindex="0" aria-controls="dataTable"
                                    rowspan="1" colspan="1"
                                    aria-label="Start date: activate to sort column ascending"
                                    style="width: 68.5px;">매니저</th>
                            </tr>
                        </thead>
                        <tbody>
                            <!-- data : List<EmpVO> empVOList
                            empVO : EmpVO
                        stat.index : 0부터 시작
                        stat.count : 1부터 시작 

                        data : ArticlePage
                        data.content : ArticlePage의 content 멤버변수(List<EmpVO>)
                         -->
                            <c:forEach var="empVO" items="${data.content}" varStatus="stat">
                                <tr class="odd trSelect">
                                    <td class="sorting_1" >${empVO.rnum}</td>
<%-- 										<td class="sorting_1">${stat.count}</td> --%>
                                    <td><a href="/emp/detail?empNum=${empVO.empNum}">${empVO.empNum}</a></td>
                                    <td>${empVO.empNm}</td>
                                    <td>${empVO.empPay}</td>
                                    <td><a class="showMj" data-bs-toggle="modal"
                                        data-bs-target="#exampleModal"
                                        data-empmjnum="${empVO.empMjNum}">${empVO.empMjNm}</a></td>
                                </tr>
                            </c:forEach>
                        </tbody>
                    </table>
                </div>
            </div>
            <div class="row">
                <div class="col-sm-12 col-md-5">
                    <div class="dataTables_info" id="dataTable_info" role="status"
                        aria-live="polite">Showing 1 to 10 of 57 entries</div>
                </div>
                <div class="col-sm-12 col-md-7">
                    <div class="dataTables_paginate paging_simple_numbers"
                        id="dataTable_paginate">
                        <ul class="pagination">
                            <li class="paginate_button page-item previous
                            <c:if test='${data.startPage lt 6}'>disabled</c:if>
                                " id="dataTable_previous"><a href="/emp/list?currentPage=${data.currentPage - size}"
                                aria-controls="dataTable" data-dt-idx="0" tabindex="0"
                                class="page-link">Previous</a></li>
                            <c:forEach var="pNo" begin="${data.startPage}" end="${data.endPage}">
                                <li class="paginate_button page-item
                                <c:if test='${param.currentPage==pNo}'>active</c:if>
                                ">
                                <a href="/emp/list?currentPage=${pNo}&keyword=${param.keyword}" 
                                    aria-controls="dataTable" data-dt-idx="1" tabindex="0"
                                    class="page-link">${pNo}</a></li>
                            </c:forEach>
                            <li class="paginate_button page-item next
                                <c:if test='${data.endPage ge data.totalPages}'>disabled</c:if>
                            " id="dataTable_next"><a
                                href="/emp/list?currentPage=${data.startPage + size}&keyword=${param.keyword}" aria-controls="dataTable" data-dt-idx="7" tabindex="0"
                                class="page-link">Next</a></li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

 

 

'JAVA > spring' 카테고리의 다른 글

[Spring] ajax 데이터 전송 전 헤더 csrf값 설정  (0) 2023.02.14
[Spring] form 태그 라이브러리  (0) 2023.02.06
[Spring] 파일 다운로드  (0) 2023.02.02
[Spring] ajax 데이터 처리  (0) 2023.02.02
[Spring] Mybatis - resultMap  (0) 2023.01.31