본문 바로가기

프로그래밍/Spring Boot 프로젝트

항공사 플랫폼 팀 프로젝트_페이징 처리

반응형

페이징 처리

PagingObj 라는 클래스를 만들어 구현함.
 
 

Define패키지 > PagingObj.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
@Data
@NoArgsConstructor
public class PagingObj {
 
    // 현재 페이지
    private Integer nowPage;
    // 시작 페이지
    private Integer startPage;
    // 끝 페이지 -> 현재 페이지에서 최대로 표시되는 마지막 페이지
    private Integer endPage;
    // 총 게시글 수 
    private Integer total;
    // 마지막 페이지 -> 마지막 게시글이 있는 페이지
    private Integer lastPage;
    // 쿼리문에 들어갈 start
    private Integer start;
    // 쿼리문에 들어갈 end
    private Integer end;
    // 한 번에 출력할 페이지 수 
    private Integer cntPage = 3;
    
    // controller에서 사용할 생성자 (총 게시글 수, 현재 페이지, 한 페이지당 게시글 수)
    public PagingObj(int total, int nowPage, int cntPerPage) {
        this.total = total;
        this.nowPage = nowPage;
        this.cntPerPage = cntPerPage;
        calcLastPage(this.total, this.cntPerPage);
        calcStartEndPage(this.nowPage, this.cntPage);
        calcStartEnd(this.nowPage, this.cntPerPage);
    }
    
    // (lastPage) 제일 마지막 페이지 계산하는 메서드
    public void calcLastPage(int total, int cntPerPage) {
        this.lastPage = (int) Math.ceil((double) total / (double) cntPerPage);
    }
    
    // 시작 끝 페이지 계산
    public void calcStartEndPage(int nowPage, int cntPage) {
        this.endPage = (int) Math.ceil(((double) nowPage / (double) cntPage) * cntPage);
        if(this.endPage < cntPage) {
           this.endPage = cntPage;
        }
        
        if(this.lastPage < this.endPage) {
            this.endPage = this.lastPage;
        }
        
        // ex) cntPage가 3이라는 전제 하에 endPage가 8일 때 startPage가 6이 되어야 한다.
        this.startPage = (this.endPage - cntPage + 1);
        if(this.startPage < 1) {
            this.startPage = 1;
        }
    }
    
    // start, end 는 게시글 no라고 생각하기
    // 쿼리에서 사용할 start, end 계산
    public void calcStartEnd(int nowPage, int cntPerPage) {
        // 15 = 3 * 5
        this.end = nowPage * cntPerPage;
        // 11 = 15 - 5 + 1
        this.start = this.end - cntPerPage + 1;
    }
 
}
cs

 
 

notice.xml
→ h2 와 mysql에서 사용하는 문법이 다르다 !

 

1. 페이징 처리 안 된 쿼리문

1
2
3
4
5
6
7
8
9
<select id="selectNotice"
        resultType="com.green.airline.dto.response.NoticeResponseDto">
        <!-- 페이징 처리 안된 쿼리문 -->
        <!-- select *, nc.name as name
        from notice_tb as n
        inner join
        notice_category_tb as nc
        on nc.id = n.category_id -->
</select>
cs

 
 

2. 페이징 처리 MySQL용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<select id="selectNotice"
        resultType="com.green.airline.dto.response.NoticeResponseDto">
<!-- 페이징 처리 MySql용 -->
        <!-- SELECT * 
        from (
             SELECT @ROWNUM := @ROWNUM + 1 AS ROWNUM, A.* 
            FROM (
                select 
                    nc.name as name, 
                            nc.id as category_id,
                            n.id as id,
                            n.title,
                            n.content,
                            n.created_at,
                from notice_tb as n
                inner join
                notice_category_tb as nc
                on nc.id = n.category_id
                ORDER BY id DESC
                ) A, 
                (SELECT @ROWNUM := 0 ) B
            ) as C
        WHERE C.ROWNUM BETWEEN #{obj.start} AND #{obj.end} -->
</select>
cs

 
 

3. 페이징 처리 h2용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<select id="selectNotice"
        resultType="com.green.airline.dto.response.NoticeResponseDto">
        SELECT * 
        FROM (
            SELECT ROWNUM RN, A.* 
                FROM (
                        select 
                            nc.name as name, 
                            nc.id as category_id,
                            n.id as id,
                            n.title,
                            n.content,
                            n.created_at,
                        from 
                        notice_tb as n
                        inner join
                        notice_category_tb as nc
                          on nc.id = n.category_id
                        order by n.id desc
                    ) A
                )
        WHERE RN BETWEEN #{start} AND #{end}
</select>
cs

 
 
+ 총 게시글 수가 필요하다. 

1
2
3
4
    select count(*) from notice_tb
cs

→ count(*) 로 총 게시물 수를 가져오기
→ resultType = “int” 잊지마 !
 
 

NoticeRepository.java

1
2
3
4
5
// 전체 공지사항 글 개수 받아오는 기능
int selectNoticeCount();
 
// 공지사항 페이징 처리
List selectNotice(PagingObj obj);
cs

 
 

NoticeService.java

1
2
3
4
5
6
7
8
9
10
11
// 페이징 처리
public List readNotice(PagingObj obj) {
    List noticeList = noticeRepository.selectNotice(obj);
    return noticeList;
}
 
// 총 게시글 수
public int readNoticeCount() {
    int resultCount = noticeRepository.selectNoticeCount();
    return resultCount;
}
cs

 
 

NoticeController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 공지사항 페이지
@GetMapping("/noticeList")
public String noticePage(Model model, @RequestParam(name = "nowPage", defaultValue = "1", required = falseString nowPage,
    @RequestParam(name = "cntPerPage", defaultValue = "5", required = falseString cntPerPage) {
    
    // PagingObj에서 가져야 할 값 -> 총 게시글 수, 현재 페이지, 한 페이지당 게시글 수
    // 총 게시글 수
    int total = noticeService.readNoticeCount();
    // 총 게시글 수, @RequestParam의 nowPage, @RequestParam의 cntPerPage
    PagingObj obj = new PagingObj(total, Integer, parseInt(nowPage), Integer.parseInt(cntPerPage));
    model.addAttribute("paging", obj);
    
    List<NoticeResponseDto> noticeList = noticeService.readNotice(obj);
    model.addAttribute("noticeList", noticeList);
    List<NoticeCategory> categoryList = noticeService.readNoticeCategory();
    model.addAttribute("categoryList", categoryList);
    
    return "/notice/noticeList";
}
cs

 
 

jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        <div style="display: block; text-align: center;">        
            <c:if test="${paging.startPage != 1}">
                <a href="/notice/noticeList?nowPage=${paging.startPage - 1}&cntPerPage=${paging.cntPerPage}"><</a>
            </c:if>
            <c:forEach begin="${paging.startPage}" end="${paging.endPage}" var="p">
                <c:choose>
                    <c:when test="${p == paging.nowPage}">
                        <b>${p}</b>
                    </c:when>
                    <c:when test="${p != paging.nowPage}">
                        <a href="/notice/noticeList?nowPage=${p}&cntPerPage=${paging.cntPerPage}">${p}</a>
                    </c:when>
                </c:choose>
            </c:forEach>
            <c:if test="${paging.endPage != paging.lastPage}">
                <a href="/notice/noticeList?nowPage=${paging.endPage+1}&cntPerPage=${paging.cntPerPage}">></a>
            </c:if>
        </div>
cs
반응형