본문 바로가기
개발/Spring

[Mybatis + Pageable] 게시판 페이징 처리

by 코딩하는 흰둥이 2024. 10. 18.

이전글

https://greed-yb.tistory.com/298

 

[Html + Javascript + Ajax + Paging] 게시판 페이징 처리

이전글https://greed-yb.tistory.com/209 [SpringBoot+IntelliJ+Oracle+Thymeleaf+Paging] 웹 게시판 만들기(1) - 구성Java 17 Maven Spring Boot 3.0.3 Oracle 11g IntelliJ Ultimate DBeaver 간단한 CRUD 만 구현해 놓았으며 순서대로 만들

greed-yb.tistory.com

 

 

 

pom.xml
<!-- Paging -->
<dependency>
	<groupId>org.springframework.data</groupId>
	<artifactId>spring-data-commons</artifactId>
</dependency>

 

 

controller
@Controller
public class WebController {

    @Autowired
    private PageTestService pageTestService;

    // 페이지에이블 테스트 게시판
    @GetMapping("/pageableTest")
    public String pageableTest() throws Exception{
        return "pageableTest";
    }

    // 페이지에이블 테스트 게시판
    @GetMapping("/pageableTestLit")
    @ResponseBody
    public Page<PageTestVo> pageableTestLit(@RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size, @RequestParam(defaultValue = "") String searchKeyWord) throws Exception{
        Pageable pageable = PageRequest.of(page,size);
        return pageTestService.selectPageable(pageable, searchKeyWord);
    }
    
}

 

 

service
public interface PageTestService {
    // 게시글 조회
    Page<PageTestVo> selectPageable(Pageable pageable, String searchKeyWord) throws Exception;
}

 

 

serviceImpl
@Service
public class PageTestServiceImpl implements PageTestService {

    @Autowired
    private PageTestMapper testMapper;

    @Override
    public Page<PageTestVo> selectPageable(Pageable pageable , String searchKeyWord) throws Exception {
        // data 가 0번째부터 시작해서 pageNumber 가 0 부터
        int rowStart = ((pageable.getPageNumber()) * pageable.getPageSize()) + 1;
        int rowEnd = (rowStart + pageable.getPageSize() -1);

        List<PageTestVo> vo = testMapper.selectPageable(pageable, rowStart, rowEnd, searchKeyWord);

        // 글의 총 개수
        int total = testMapper.totalPageable(searchKeyWord);

        return new PageImpl<>(vo, pageable, total);
    }
}

 

 

mapper.class
@Mapper
public interface PageTestMapper {
    List<PageTestVo> selectPageable(@Param("pageable") Pageable pageable, 
    				    @Param("rowStart") int rowStart,
                                    @Param("rowEnd") int rowEnd,
                                    @Param("searchKeyWord") String searchKeyWord) throws Exception;

    int totalPageable(String searchKeyWord) throws Exception;
}

 

 

mapper.xml
    <select id="selectPageable" resultType="com.example.practice.vo.pageTest.PageTestVo">
        SELECT *
        FROM (SELECT ROW_NUMBER() OVER(ORDER BY NO DESC) AS NUM,
        NO,
        CONTENT
        FROM PAGETEST
        <if test="searchKeyWord != null">
            WHERE CONTENT LIKE '%' || #{searchKeyWord} || '%'
        </if>
        )
        WHERE NUM BETWEEN #{rowStart} AND #{rowEnd}
    </select>


    <select id="totalPageable" resultType="int">
        SELECT COUNT(NO) FROM PAGETEST
        <if test="searchKeyWord != null">
            WHERE CONTENT LIKE '%' || #{searchKeyWord} || '%'
        </if>
    </select>

 

 

html
<div class="card-body">
    <div class="table-responsive">
        <select class="form-select" id="searchSize">
            <option value="10">10개</option>
            <option value="30">30개</option>
            <option value="50">50개</option>
        </select>
        <div class="row">
            <div class="col-sm-6 mb-3 mb-sm-0">
                <input type="text" class="form-control form-control-user" id="searchKeyWord" placeholder="제목">
            </div>
            <button class="btn btn-primary" type="button" id="pageTestBtn" onclick="searchBtn()">검색</button>
        </div>
        <table class="table table-bordered" id="board_dataTable" style="width: 98%">
            <thead>
            <tr>
                <th>No</th>
                <th>제목</th>
            </tr>
            </thead>
            <tbody>
            <!-- 글 목록 -->
            </tbody>
        </table>
        <!-- bootstrap css -->
        <div id="pagingBar">
            <ul class="pagination justify-content-center" id="pagingUl"></ul>
        </div>
    </div>
</div>

 

 

javascript
// 페이지 기본값
let page = 0;
let size;
let searchKeyWord;


/**
 * 보여지는 글 개수 변경 시
 */
$("#searchSize").change(function (){
    page = 0;
    size = $("#searchSize").val();
    searchKeyWord = $("#searchKeyWord").val();

    search();
})

/**
 * BootStrap 페이지 바 생성
 */
function pageBar(data){
    // 페이지 개수
    let pageSize = 10;
    let currentGroup = Math.floor((data.number) / pageSize) ;

    let startPage = (currentGroup * pageSize) ;
    let endPage = Math.min(startPage + pageSize , data.totalPages);

    if(currentGroup > 0){
        $('#pagingUl').append(`<li class="page-item"><a href="#" class="page-link" data-page="${startPage -1}">이전</a></li>`);
    }

    for (let i = startPage; i < endPage; i++) {

        let active = (i === data.number) ? 'active' : '';

        $('#pagingUl').append(`<li class="page-item ${active}"><a href="#" class="page-link" id="pageNum_${i}" data-page="${i}">${i+1}</a></li>`);
    }

    if(endPage < data.totalPages){
        $('#pagingUl').append(`<li class="page-item"><a href="#" class="page-link" data-page="${endPage}">다음</a></li>`);
    }

}

/**
 * 페이지 이동
 */
$("#pagingBar").on("click", "a", function (){
    page = $(this).data("page");
    search();
})

/**
 * 검색 버튼
 */
function searchBtn(){
    page = 0;
    search();
}

/**
 * 검색
 */
function search(){
    size = $("#searchSize").val();
    searchKeyWord = $("#searchKeyWord").val();

    $.ajax({
        url : "/pageableTestLit",
        method : "GET",
        data : { "page": page, "size" : size , "searchKeyWord" : searchKeyWord},
        success : function (data){
            // 목록 초기화
            $("#board_dataTable tbody").empty();

            // 페이지 바 초기화
            // $('#pagingBar').empty();    // css 미적용
            $('#pagingUl').empty();  // bootstrap css 적용

            if(data.content.length > 0 ){
                for (let i = 0; i < data.content.length; i++) {
                    $("#board_dataTable").append('<tr><td>'+ data.content[i].no +'</td><td>'+ data.content[i].content +'</td></tr>');
                }

                pageBar(data);


            }else{
                $("#board_dataTable").append('<tr><td colspan="2">데이터가 없습니다.</td></tr>');
            }
        }
    })
}


$(document).ready(function (){
    // 검색
    search();
});

 

 

sort 기능을 사용하고 싶다면

controller 의

PageRequest.of(page,size); 부분에 3번째 인자값으로 sort 값을 넣으면 된다

직접 해보지 않았기 때문에 예시 코드는 넣지 않겠다

참고로 sort 를 넣게 된다면 쿼리에도 코드를 수정해줘야 한다

 

쿼리에 between 사용 시 Pageableoffsetpagesize 를 이용해도 되는데

따로 계산하기가 귀찮아서 사용하지 않았다.

 

 

이전글에서 만들었던

PageMaker, SearchMaker Class 보다 

Spring 에서 제공하는 Pageable 이 확실히 간편한 거 같다

댓글