본문으로 바로가기

[전체공연List]전체 공연 출력하기 / 페이징 처리

category 프로젝트 2020. 4. 8. 17:10

구현 내용

DB에 있는 공연 내역 전부를 가져와 리스트 형태로 보여주되,

한페이지에 10개씩 표기되도록 페이징 처리를 하여 사용자가 보기 편하도록 구현함.

 

 

핵심 코드

[HomeServiceImpl.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
    @Override
    public void list(HttpServletRequest request) {
        
        //한 페이지에 나타낼 row 의 갯수
        final int PAGE_ROW_COUNT=10;
        //하단 디스플레이 페이지 갯수
        final int PAGE_DISPLAY_COUNT=5;
        
        //보여줄 페이지의 번호
        int pageNum=1;
        //보여줄 페이지의 번호가 파라미터로 전달되는지 읽어와 본다.    
        String strPageNum=request.getParameter("pageNum");
        if(strPageNum != null){//페이지 번호가 파라미터로 넘어온다면
            //페이지 번호를 설정한다.
            pageNum=Integer.parseInt(strPageNum);
        }
        //보여줄 페이지 데이터의 시작 ResultSet row 번호
        int startRowNum=1+(pageNum-1)*PAGE_ROW_COUNT;
        //보여줄 페이지 데이터의 끝 ResultSet row 번호
        int endRowNum=pageNum*PAGE_ROW_COUNT;
        
        //전체 row 의 갯수를 읽어온다.
        int totalRow=dao.getCount(dto);
        //전체 페이지의 갯수 구하기
        int totalPageCount=(int)Math.ceil(totalRow/(double)PAGE_ROW_COUNT);
        //시작 페이지 번호
        int startPageNum=1+((pageNum-1)/PAGE_DISPLAY_COUNT)*PAGE_DISPLAY_COUNT;
        //끝 페이지 번호
        int endPageNum=startPageNum+PAGE_DISPLAY_COUNT-1;
        //끝 페이지 번호가 잘못된 값이라면 
        if(totalPageCount < endPageNum){
            endPageNum=totalPageCount; //보정해준다. 
        }        
        //Dto 객체에 위에서 계산된 startRowNum 과 endRowNum 을 담는다.
        dto.setStartRowNum(startRowNum);
        dto.setEndRowNum(endRowNum);
        
        List<FullCalendarDto> list=dao.getList(dto);
        request.setAttribute("list", list);
        
        //EL, JSTL 을 활용하기 위해 필요한 모델을 request 에 담는다.
        
        request.setAttribute("pageNum", pageNum);
        request.setAttribute("startPageNum", startPageNum);
        request.setAttribute("endPageNum", endPageNum);
        request.setAttribute("totalPageCount", totalPageCount);
        request.setAttribute("totalRow", totalRow);
        
    }
cs

1.하단에 표시될 페이지의 전체 개수

전체 데이터의 row/한 페이지에 나타낼 row의 수를 하면 하단에 표시될 페이지의 전체 개수를 알 수 있다.

주의!

정확하게 값이 떨어지지 않고 10.1 등으로 실수가 나오는 경우가 있다.

예시) 전체 글의 개수가 101개 이고 한 페이지에 10개씩 표기 하려는 경우, 10.1 이 나온다.

  , 글을 10페이지에 표기하고 1개의 글이 남는다는 뜻이다.

이 경우, 해당 글까지 모두 총 11페이지에 표시가 되어야 하므로 정확한 값이 나올 수 있도록 int(정수) double(실수) 나누어 실수까지 표기될 수 있도록 해야 한다.

나머지 데이터 1개를 위한 페이지를 추가로 만들기 위해 ceil()메서드를 사용해 올림처리를한다. 결과적으로 정수 11 totalPageCount 변수에 담기게 된다.

 

2. 페이지의 시작번호

하단에 표시될 전체 페이지가 15개이고, 한번 표시될 때 5개씩 표시를 하기로 가정해보자.

그렇다면 클라이언트에 표기되는 페이지는 이렇게 될 것이다.

< 1  2  3  4  5 >

< 6  7  8  9  10 >

<11 12 13 14 15 >

클라이언트가 1,2,3,4,5 페이지 중 하나를 클릭하더라도 페이지는 넘어가지 않고 계속 1~5사이의 숫자 표기하는 것을 유지해야한다.

우선, 계산식을 살펴보기 전에 한가지를 꼭 기억하자.

정수를 cating 해주지 않으면 java에서는 default int값으로 정의한다. 따라서 실수로 나올 경우 소수점자리는 절삭되어 정수 값만 유지된다.

 

pageNum 2를 넣고 , PAGE_DISPLAY_COUNT를 넣어보면 0.2가 계산된다 그러나 따로 캐스팅을 해주지 않았으므로 int로 인식되어 소수점 자리는 절삭된다. 결과적으로 0이 계산 결과로 나온다.

따라서 1~5 어느 페이지를 클릭하더라도 페이지의 시작 번호는 항상 1이 된다.

 

3. 페이지의 끝 번호

페이지의 끝 번호는 페이지의 시작번호와 끝 번호를 더해준 뒤 -1을 해주면 된다.

 

만약 총 표시되어야 하는 페이지가 13개 인 경우, 11~15까지 모두 표시가 된다면 페이지를 보는 사람들은 데이터가 없는 페이지를 클릭했을때 혼란을 느낄 것이다.

이 코드는 데이터가 표시되지 않는 페이지를 표기하지 않는다.

총 표기 되어야하는 페이지의 수 보다 마지막 페이지가 크다면 마지막으로 표시 되어야하는 페이지 대신 전체 페이지의 개수를 넣어준다.

 

 

[HomeMapper.xml]

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="getList" parameterType="fullCalendarDto" resultType="fullCalendarDto">
        SELECT *
         FROM (SELECT result1.*, ROWNUM AS rnum
                FROM (SELECT seq, title, TO_CHAR(startdate,'YYYY/MM/DD') AS startdate, TO_CHAR(enddate,'YYYY/MM/DD') AS enddate, place, thumbnail, likecount
                        FROM tb_api_date
                        <choose>
                            <when test="startdate != null and enddate != null">
                                <![CDATA[
                                WHERE startdate>=to_date(${startdate},'yyyymmdd') AND startdate<=to_date(${enddate},'yyyymmdd')
                                ]]>
                            </when>
                            <when test="title != null">
                                WHERE title LIKE '%${title}%'
                            </when>
                            <when test="place != null">
                                WHERE place LIKE '%${place}%'
                            </when>
                        </choose>
                        order by
                            startdate DESC
 
                        ) result1)
         WHERE rnum BETWEEN #{startRowNum} AND #{endRowNum}
    </select>
cs

가장 최근에 시작한 공연순서대로 정렬한 뒤, ROWNUM 예약어를 이용해 DATA에 번호를 매겨준다.

그리고 글릭한 페이지에 해당하는 data가 출력될 수 있도록 where 구문을 이용해 필요한 데이터만 select 하여 Dto에 담는다.

 

[list.jsp]

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
    <table class="table table-hover">
        <thead>
            <tr class="title">
                <th>공연명 </th>
                <th>좋아요</th>
                <th>장소</th>
                <th>공연기간</th>
            </tr>
        </thead>
        <tbody>
            <c:forEach var="tmp" items="${requestScope.list }">
                <tr class="tr">
                    <td>
                        <a href="detail.do?seq=${tmp.seq }">
                            ${tmp.title }
                        </a>                
                    </td>                
                    <td>
                        <img class="heart" src="${pageContext.request.contextPath }/resources/images/red-heart.png" alt="" />
                        ${tmp.likeCount }
                    </td>                
                    <td>${tmp.place }</td>
                    <td>${tmp.startdate } ~ ${tmp.enddate }</td>
                </tr>    
            </c:forEach>
        </tbody>    
    </table>
cs

반복문을 돌면서 list에 담긴 데이터를 출력해준다.