오답노트

게시판 페이징 처리하기 feat. ORACLE

titlejjk 2023. 6. 9. 09:36

게시판 페이징 처리하기

강사님이 내주신 과제인데 손에도 안잡혀서 코드 받고 분석만 해보았다. 이해라도 잘해야지..

먼저 해당 게시판에 페이지 번호를 부여해주었다.

<%
   int pageNum = 1;
   if(request.getParameter("pageNum") != null){
      pageNum = Integer.parseInt(request.getParameter("pageNum"));
   }
   
   List<FileDto> listPage = FileDao.getInstance().getListPage(pageNum);
   //로그인된 아이디(로그인이 되어있지 않으면 null)
   String id = (String)session.getAttribute("id");
%>

int pageNum = 1;

아래 코드는 for문을 돌아 i가 1부터 10까지 출력되도록 해주었다.

pageNum을 1로 초기값으로 설정해주면 페이지로딩시 1페이지가 출력되도록 설정

<ul class="pagination justify-content-center">
         <%for(int i = 1; i < 10; i++) {%>
            <li class="page-item">
               <a class="page-link" href="list.jsp?pageNum=<%=i %>"><%=i %></a>
            </li>
         <%} %>
      </ul>

이렇게 하면 1번째 페이지가 출력이 된다.

그리고 2번을 누르면 페이지 전환이 되도록 하는코드는 위에 써있는 것처럼

 if(request.getParameter("pageNum") != null){
      pageNum = Integer.parseInt(request.getParameter("pageNum"));
   }

해석해보자면 pageNum이 null이 아닐경우 request.getParameter로 들어온 값의 페이지 번호가 pageNum에 담겨 해당 번호의 페이지가 출력이 된다.

 

다음으로 해당 페이지를 눌렀을 때 게시글 수를 출력하는 메소드(오라클DB를 통해 가져옴)

//파일 목록을 리턴하는 메소드
	   public List<FileDto> getListPage(int num){
	      //파일 목록을 담을 ArrayList 객체 생성
	      List<FileDto> list = new ArrayList<FileDto>();
	      
	      //필요한 객체의 참조값을 담을 지역변수 미리 생성
	      Connection conn = null;
	      PreparedStatement pstmt = null;
	      ResultSet rs = null;
	      try {
	         //DbcpBean 객체를 이용해서 Connection 객체를 Connection Pool에서 얻어오기
	         conn = new DbcpBean().getConn();
	         //실행할 sql문
	         String sql = "SELECT *"
	               + " FROM"
	               + "    (SELECT result1.*, ROWNUM AS rnum"
	               + "    FROM"
	               + "       (SELECT num, writer, title, orgFileName, saveFileName, fileSize, regdate"
	               + "       FROM board_file"
	               + "       ORDER BY num DESC) result1)"
	               + " WHERE rnum BETWEEN ? AND ?";
	         pstmt = conn.prepareStatement(sql);
	         pstmt.setInt(1, (num-1)*10+1);//페이지번호
	         pstmt.setInt(2, num*10);
	         rs = pstmt.executeQuery();
	         //반복문 돌면서 ResultSet에 담긴 내용 추출
	         while (rs.next()) {
	            FileDto dto = new FileDto();
	            dto.setNum(rs.getInt("num"));
	            dto.setWriter(rs.getString("writer"));
	            dto.setTitle(rs.getString("title"));
	            dto.setOrgFileName(rs.getString("orgFileName"));
	            dto.setSaveFileName(rs.getString("saveFileName"));
	            dto.setFileSize(rs.getLong("fileSize"));
	            dto.setRegdate(rs.getString("regdate"));
	            
	            list.add(dto);
	         }
	      } catch (SQLException se) {
	         se.printStackTrace();
	      } finally {
	         try {
	            if (rs != null) {
	               rs.close();
	            }
	            if (pstmt != null) {
	               pstmt.close();
	            }
	            if (conn != null) {
	               conn.close();
	            } //Connection이 Connection Pool에 반납됨
	         } catch (Exception e) {
	         }
	      }
	      
	      return list;
	   }
String sql = "SELECT *"
	               + " FROM"
	               + "    (SELECT result1.*, ROWNUM AS rnum"
	               + "    FROM"
	               + "       (SELECT num, writer, title, orgFileName, saveFileName, fileSize, regdate"
	               + "       FROM board_file"
	               + "       ORDER BY num DESC) result1)"
	               + " WHERE rnum BETWEEN ? AND ?";
	         pstmt = conn.prepareStatement(sql);
	         pstmt.setInt(1, (num-1)*10+1);//페이지번호
	         pstmt.setInt(2, num*10);

아래 SQL문을 해석해보자면

1. 조회할 데이터들을 나열하고 SELECT num, writer, title, orgFileName, saveFileName, fileSize, regdate

어느  테이블에서 FROM board_file

어떤 식으로 나열할건지 ORDER BY num DESC 이렇게 해주고

2. 1번은 result1으로 감싸서 다시 result1을 조회하고 SELECT result1의 전체를 *로 조회한다.

어느 방식으로 ? ROWNUM으로 이 ROWNUM AS를 통해 뒤에는 rnum이라 써주기로하고

3. 2번을 SELECT 해준다. SELECT * FROM 2번

어떤조건으로? rnum 이 BETWEEN ? AND ? 1번 물음표에서 2번 물음표 까지.

 

pstmt.setInt(1, (num-1)*10+1);

위 코드는 첫 번째 물음표를 설정해주는데 만약 2가 들어가면 (2-1)*10+1을 통해 11번째 db row부터 검색이 되고

pstmt.setInt(2, num*10);

위 코드는 두 번째 물음표를 설정해주는데 위처럼 2가 들어가게 되면 2*10번째 즉 20번째 db row가 검색이된다.

위 SQL 문에서 BETWEEN ? AND ? 이니 최종적으로 11번째 부터 20번의 db가 조회되는 메소드이다.