반응형

항상 오라클만 썻던 나에게는 

오라클 처럼 rownum으로 하면 되겠지?? 

라고 생각하던 차에 새로 만들고 있는 웹사이트에서 행복 회로를 돌리며 

매퍼작성을 끝냇는데

응 ?? badsql?? 읭 왜?? 

나의 착오 였다.

 

그렇다 

MYSQL에서는 ROWNUM을 지원하지 않아 

다른 문법으로 해야한다. 

 

그래서 폭풍 검색끝에 limit이라는 걸 찾아 냈다.

오히려 오라클보다 너무 쉬워 까먹기전에 포스팅을 해야겠다고 생각했다. 

 

우선 구현한 페이지를 보자 

 

 

우선 페이지삼아 더미데이터를 약 2만 7천개 정도 넣었다 .

10만개가 안되면 데이터테이블쓰는게 이롭지만.. 

 

각설 하고 기존 오라클 페이징 에서 크게 벗어나지는 않는다. 

 

 

우선 모델 객체부터 살펴보자 .

 

PageVO 객체

@Getter
@Setter
@ToString
public class PageVO {

	//사용자가 선택한 페이지 정보를 담을 변수.
	private int pageNum;
	private int countPerPage;
	
	//검색에 필요한 데이터를 변수로 선언.
	private String keyword;
	private String condition;
	
	public PageVO() {
		this.pageNum = 1;
		this.countPerPage = 10;
	}
}

앞서 설명한거와 같이 사용자가 선택한 페이지 정보를 담고 

검색은 키워드와 컨디션으로 통일한다. 

그리고 생성자를 하나 꺼내 맨 처음 페이지 1과 페이지에 보여줄 게시글 수 10개를 선택해준다. 

 

 

PageCreate 객체

@Getter
@Setter
@ToString
public class PageCreate {

	private PageVO paging;
	private int articleTotalCount;
	private int endPage;
	private int beginPage;
	private boolean prev;
	private boolean next;
	
	private final int buttonNum = 5;
	
	
	private void calcDataOfPage() {
		
		endPage = (int) (Math.ceil(paging.getPageNum() / (double) buttonNum) * buttonNum);
		
		beginPage = (endPage - buttonNum) + 1;
		
		prev = (beginPage == 1) ? false : true;
		
		next = articleTotalCount <= (endPage * paging.getCountPerPage()) ? false : true;
		
		if(!next) {
			endPage = (int) Math.ceil(articleTotalCount / (double) paging.getCountPerPage()); 
		}
		
	}
	
	public void setArticleTotalCount(int articleTotalCount) {
		this.articleTotalCount = articleTotalCount;
		calcDataOfPage();
	}

그 후 endpage next 등 페이지를 설정 해준다. 

여기서 setArticleTotalCount는

컨트롤러에서 총 게시물의 개수를 PageCreate에게 전달한 직후에

바로 페이징 버튼 알고리즘이 들어수 있도록 setter를 약간의 커스텀을 해줆.

 

그 후  검색을 할수 있게 아래와 같이 sql문을 매퍼에 작성해준다. 

 

1. 특정 문자로 시작하는 데이터 검색

SELECT [필드명] FROM [테이블명] WHERE [필드명] LIKE '특정 문자열%';

 

2. 특정 문자로 끝나는 데이터 검색

SELECT [필드명] FROM [테이블명] WHERE [필드명] LIKE '%특정 문자열';

 

3. 특정 문자를 포함하는  데이터  검색

SELECT [필드명] FROM [테이블명] WHERE [필드명] LIKE '%특정 문자열%';

 

 

 

[MySQL]
title like CONCAT('%',#{keyword},'%')


[Oracle]
title like '%' ||  #{keyword} || '%'


[MSSQL]
title like '%' + #{keyword} + '%'

로 지정해주면 된다.

	<sql id="search">
		<if test="condition == 'freeboard_title'">
			WHERE freeboard_title LIKE CONCAT('%',#{keyword},'%')
		</if>
		<if test="condition == 'freeboard_content'">
			WHERE freeboard_content LIKE CONCAT('%',#{keyword},'%')
		</if>
		<if test="condition == 'freeboard_writer'">
			WHERE freeboard_writer LIKE CONCAT('%',#{keyword},'%')
		</if>
	</sql>
     <!-- 토탈 -->
     	<select id="getTotal" resultType="int">
		SELECT COUNT(*)
		FROM Vegan_freeBoard
		<include refid="search" />
	</select>
    
      <select id="getFreeBoard" resultType="com.vegan.recipe.freeBoard.freeboardVO">
     	select * from Vegan_freeBoard 
     	<include refid="search" />
     	order by freeboard_no desc
     	limit #{pageNum} ,  #{countPerPage}
     </select>

 

토탈을 구해주고 리밋으로 페이지넘과 페이지 수를 전달해준다. 

 

컨트롤러 부분

 

	@GetMapping("/freeList")
	public String getFree(Model model, PageVO vo) {
		PageCreate pc = new PageCreate();
		pc.setPaging(vo);
		pc.setArticleTotalCount(service.getTotal(vo));
		
		System.out.println(pc);
		
		model.addAttribute("freeList", service.getFreeBoard(vo));
		model.addAttribute("pc", pc);
		
		return "FreeBoard/freeList";
	}

 

페이지 크리에이트 와 pagevo 객체를 변수 로 선택해주고 모델로 뷰로 날려준다.

 

    </div>
	
                 <form action="<c:url value='/FreeBoard/freeList'/>">
                        <div class="search-wrap clearfix">
                            <button type="submit" class="btn btn-primary search-btn" style="margin-right: 24%;">검색</button>
                            <input type="text" name="keyword" class="form-control search-input" value="${pc.paging.keyword}"
                            style="width: 200px; ">
                            <select class="form-control" id="search-select" name="condition" style="width: 80px; margin-left: 54%">
                                <option value="freeboard_title" ${pc.paging.condition == 'freeboard_title' ? 'selected' : ''}>제목</option>
                                <option value="freeboard_content" ${pc.paging.condition == 'freeboard_content' ? 'selected' : ''}>내용</option>
                                <option value="freeboard_writer" ${pc.paging.condition == 'freeboard_writer' ? 'selected' : ''}>작성자</option>
                            </select>
                        </div>
                    </form> 
	
    <!-- 비건 뉴스 상세보기 -->
    <table class="table" style="width: 70%; margin: 0 auto;">
        <thead>
          <tr>
            <th scope="col">#</th>
            <th scope="col">제목</th>
            <th scope="col">작성자</th>
            <th scope="col">작성 시간</th>
            <th scope="col">조회수</th>
            <th scope="col">좋아요</th>
          </tr>
        </thead>
        <tbody>
        <c:forEach var="vo" items="${freeList}">
          <tr>
          	<th scope="row">${vo.freeboard_no}</th>
            <td><a href="<c:url value='/FreeBoard/freeDetail?freeboard_no=${vo.freeboard_no}'/>">${vo.freeboard_title}</a></td>
            <td>${vo.freeboard_writer}</td>
            <td>${vo.freeboard_regDate}</td>
            <td>${vo.freeboard_hit}</td>
            <td>${vo.freeboard_like}</td>
          </tr>
         </c:forEach>
        </tbody>
      </table>

            <!-- 글작성 -->

            <div class="newsWrite">
                <button type="button" class="btn btn-primary whyBtn">글작성</button>
              </div>
        
              <!-- 페이징 -->
        
			<div class="paging">
					<form action="<c:url value='/FreeBoard/freeList' />" name="pageForm">
	                        <div class="text-center clearfix">
	                            <ul class="pagination" id="pagination">
	                            	<c:if test="${pc.prev}">
	                                	<li class="page-item "><a  class="page-link" href="#" data-pageNum="${pc.beginPage-1}">Prev</a></li>
	                                </c:if>
	                                
	                                <c:forEach var="num" begin="${pc.beginPage}" end="${pc.endPage}">
	                                	<li class="${pc.paging.pageNum == num ? 'age-item active' : ''}" page-item><a class="page-link" href="#" data-pageNum="${num}">${num}</a></li>
	                                </c:forEach>
	                                
	                                <c:if test="${pc.next}">
	                               		<li class="page-item"><a class="page-link" href="#" data-pageNum="${pc.endPage+1}">Next</a></li>
	                                </c:if>
	                            </ul>
	                            
	                            <!-- 페이지 관련 버튼을 클릭 시 같이 숨겨서 보낼 값 -->
	                            <input type="hidden" name="pageNum" value="${pc.paging.pageNum}">
	                            <input type="hidden" name="countPerPage" value="${pc.paging.countPerPage}">
	                            <input type="hidden" name="keyword" value="${pc.paging.keyword}">
	                            <input type="hidden" name="condition" value="${pc.paging.condition}">
	                            
	                        </div>
                        </form>
			</div>
                        
<%@include file="../include/footer.jsp"%>
</body>

<script>
	$(function() {
		$('.whyBtn').click(function() {
			location.href = '<c:url value="/FreeBoard/freeWrite"/>';
		})
		$('#pagination').on('click', 'a', function(e) {
			e.preventDefault();
			console.log($(this));
			const value = $(this).data('pagenum');
			console.log(value);
			document.pageForm.pageNum.value = value;
			document.pageForm.submit();
		});
		
	})
</script>
</html>

그 후 검색으로 올 수 있도록 select로 option값을 준다. 그 뒤 컨트롤러로 보내 sql문을 타게해 조회된 결과를 보여주면 된다. 

 

페이징 같은 경우는 hidden으로 값을 숨겨 보낸뒤 자바스크립트로 마무리를 해주었다. 

 

 

 

작동이 아주 잘된다. 

 

https://github.com/MoonSeokHyun

반응형

+ Recent posts