[스프링] 페이징(검색) + 오라클(Mybatis)

손성우·2021년 7월 19일
1

스프링

목록 보기
1/9

페이징 공부한 내용을 정리해 본다.


출처 : https://freehoon.tistory.com/112

페이징은 여러 곳에서 쓰이므로 재사용성을 위해 객체로 만든다.

1. Pagination 클래스

Getter/Setter는 생략한다.

public class Pagination {

	private int currPageNo;/// 현재 페이지 번호
	private int sizePerPage = 10; // 한 페이지당 보여질 리스트 개수
	private int totalCnt; // 전체 목록 개수
	private int pageCnt; // 전체 페이지 개수
	
	private int startList; // 게시판 시작 번호
	private int range = 1; // 페이지 범위.    1 : 1~5     2: 6~10   ...
	private int pageSize = 5; // 한 페이지 범위에 보여질 페이지 개수
	private int startPage; // 각 페이지 범위의 시작 번호
	
	// 검색
	private String searchType; // 검색타입 (글제목, 글쓴이 등등)
	private String keyword; // 키워드
	
	public String getStatus() {
		return status;
	}
	public void setStatus(String status) {
		this.status = status;
	}

	private String fromDate; // 날짜 기한
	private String toDate; // 날짜 기한
	
	private int endPage; // 각 페이지 범위 끝 번호
	
	private boolean prev; // 이전 페이지 여부
	private boolean next; // 다음 페이지 여부
    
    // 핵심
    public void pageInfo(int currPageNo, int range, int totalCnt) {
		this.currPageNo = currPageNo;
		this.range = range;
		this.totalCnt = totalCnt;
		
		// 전체 페이지 수
		this.pageCnt = (int) Math.ceil((double)totalCnt/sizePerPage);
		// 시작 페이지
		this.startPage = (range - 1) * pageSize + 1;
		// 끝 페이지
		this.endPage = range * pageSize;
		// 게시판 시작 번호
		this.startList = (currPageNo - 1) * sizePerPage + 1;
		// 이전 버튼 상태
		this.prev = range == 1 ? false : true;
		// 다음 버튼 상태
		this.next = endPage >= pageCnt ? false : true;
		if(this.endPage > this.pageCnt) {
			this.endPage = this.pageCnt;
			this.next = false;
		}
		
	}
}

다음 버튼 활성화를 정리하자면, endPage는 range(페이지 범위)를 기준으로 한 마지막 페이지다
pageCnt(전체 페이지)가 9개면 range가 2이므로 endpage는 10이다. pageCnt가 endPage보다 작으니 다음버튼은 비활성화 되어야 한다. endPage를 pageCnt로 바꿔준다.

2. 게시글 목록

@RequestMapping(value="/list.action", method= RequestMethod.GET)
	public ModelAndView boardList(HttpServletRequest request, ModelAndView mav, 
			@RequestParam(value = "currPageNo", required = false, defaultValue = "1") String tmpcurrPageNo, 
   	 		@RequestParam(value = "range", required = false, defaultValue = "1") String tmprange) {
		
		int currPageNo = 0;
		int range = 0;
		
		try {			
			currPageNo = Integer.parseInt(tmpcurrPageNo);
			range = Integer.parseInt(tmprange);
			
		} catch(NumberFormatException e) {
			currPageNo = 1;
			range = 1;			
		}
		
		List<BoardVO> boardList = null;
		
		String searchType = request.getParameter("searchType");
		String keyword = request.getParameter("keyword");
	        
		if(searchType == null || (!"subject".equals(searchType) && !"name".equals(searchType)) ) {
	       searchType = "";
	    }
	      
	    if(keyword == null || "".equals(keyword) || keyword.trim().isEmpty() ) {
	       keyword = "";
	    }	   	

	    Map<String, String> paraMap = new HashMap<>();
		paraMap.put("searchType", searchType);
		paraMap.put("keyword", keyword);		
	    
	    Pagination pg = new Pagination();
	    pg.setSearchType(searchType);
	    pg.setKeyword(keyword);
	    
	    int totalCnt = boardService.boardTotalCnt(pg);	   
	    pg.pageInfo(currPageNo, range, totalCnt);
	    boardList = boardService.boardListPaging(pg);
	    
		HttpSession session = request.getSession();		
		
		if(!"".equals(searchType) && !"".equals(keyword)) {
	        mav.addObject("paraMap", paraMap);
	    }

		mav.addObject("pagination", pg);
		mav.addObject("boardList", boardList);
		mav.setViewName("board/boardList.tiles1");
		return mav;			
		
	}

RequestParam으로 currPageNo와 range를 받아온다. GET방식의 호출이므로 사용자가 URI에 문자열을 입력하는 장난을 방지하기 위해 try-catch문으로 예외처리를 해준다.
그 밑에 if문으로 URI에 serachType의 장난방지와 keyword의 공백처리를 해준다. serachType과 keyword를 Map에 담아 페이지로 전달해주는 이유는 검색내용을 페이지에 유지하기 위해서이다.

3. Mybatis

<!-- 페이징 검색 게시글 수 -->
    <select id="boardTotalCnt" parameterType="pagination" resultType="int">
    	select count(*)
    	from tbl_board
    	where 1=1
    	<choose>
    		<when test="searchType neq ''">
    		and lower( ${searchType} ) like '%'|| lower(#{keyword}) ||'%'
    		</when>
    	</choose>
    </select>
    <!-- 페이징 리스트 -->
    <select id="boardListPaging" parameterType="pagination" resultType="boardVO">
    	select *
			from(
			    select rownum as rnum, t.*
			    from
			    (
			        select *
			        from tbl_board
			        where 1=1
			        <choose>			        
			        <when test="searchType neq ''">
			        and lower( ${searchType} ) like '%'|| lower(#{keyword}) ||'%'
			        order by seq desc
			        </when>
			        </choose>
			    ) t
			    where rownum <![CDATA[<=]]> #{startList}+#{sizePerPage}
			)
		where rnum <![CDATA[>=]]> #{startList}
    </select>

where절에 lower( ${searchType} )를 하는 이유는 대소문자 구분 없이 모두 검색해주기 위해 해당 칼럼을 모두 소문자로 바꿔주는 것이다.

4. 프론트

<div>
		<nav aria-label="Page navigation example" style="margin: auto;">
			<ul class="pagination justify-content-center">
				<c:if test="${pagination.prev}">
					<li class="page-item"><a class="page-link" href="#" onClick="fn_prev('${pagination.currPageNo}', '${pagination.range}', '${pagination.pageSize}')">이전</a></li>
				</c:if>
				<c:forEach begin="${pagination.startPage}" end="${pagination.endPage}" var="idx">
					<li class="page-item <c:out value="${pagination.currPageNo == idx ? 'active' : ''}"/> "><a class="page-link" href="#" onClick="fn_pagination('${idx}', '${pagination.range}')"> ${idx} </a></li>
				</c:forEach>
				<c:if test="${pagination.next}">
					<li class="page-item"><a class="page-link" href="#" onClick="fn_next('${pagination.currPageNo}', '${pagination.range}', '${pagination.pageSize}')" >다음</a></li>
				</c:if>
			</ul>
		</nav>
	</div>
    
<script>    
//이전 버튼
function fn_prev(currPageNo, range, pageSize) {

	var currPageNo = (range - 1) * pageSize;
	var range = range - 1;

	var url = "/list.action";
	url = url + "?currPageNo=" + currPageNo;
	url = url + "&range=" + range;
	url = url + "&searchType=" + $("#searchType").val();
	url = url + "&keyword=" + $("#keyword").val();
	location.href = url;

}

//페이지 번호 클릭

function fn_pagination(currPageNo, range) {

	var url = "/list.action";
	url = url + "?currPageNo=" + currPageNo;
	url = url + "&range=" + range;
	url = url + "&searchType=" + $("#searchType").val();
	url = url + "&keyword=" + $("#keyword").val();
	location.href = url;	

}
//다음 버튼 이벤트
function fn_next(currPageNo, range, pageSize) {

	var currPageNo = (range * pageSize) + 1;
	var range = parseInt(range) + 1;	

	var url = "/list.action";
	url = url + "?currPageNo=" + currPageNo;
	url = url + "&range=" + range;
	url = url + "&searchType=" + $("#searchType").val();
	url = url + "&keyword=" + $("#keyword").val();
	location.href = url;
}

</script>    

검색 조건이 추가됨에 따라 Pagination 클래스에 변수를 추가하고 url = url + OO을 추가해주는 식으로 확장할 수 있다.

profile
백엔드 개발자를 꿈꾸며 공부한 내용을 기록하고 있습니다.

0개의 댓글