본문 바로가기
수업 일지/Spring

67일차 - [Spring] 게시판 페이징 처리

by 쿠쿠씨 2022. 4. 13.
반응형

게시판 페이징 처리

게시물의 목록을 최신글부터 출력합니다.

페이지 숫자를 클릭하면 해당 페이지로 이동합니다.

[<<] / [>>] 버튼을 누르면 맨 앞/ 맨 뒤 페이지로 이동합니다.

[>] 버튼을 누르면 다음 페이지 목록(11~20)의 시작 페이지(11)로 이동합니다.

[<] 버튼을 누르면 이전 페이지 목록의 마지막 페이지로 이동합니다.

 

DataBase

테이블 생성 및 데이터 추가

CREATE TABLE freeboard(
	idx number(5) NOT NULL,
	name varchar2(30) NOT NULL,		--작성자
	password varchar2(10) NOT NULL,		--글 비밀번호
	subject varchar2(40) NOT NULL,		--글 제목
	content varchar2(2000) NOT NULL,	--글 내용
	readCount number(5) DEFAULT '0',	--조회수
	wdate DATE DEFAULT sysdate,		--작성 날자와 시간 기본값
	ip varchar2(15) DEFAULT '127.0.0.1',	--선택
	commentCount number(3) DEFAULT '0',	--댓글 개수
	PRIMARY KEY(idx)
);

idx는 freeboard 테이블의 기본키이며 시퀀스를 사용합니다. (오라클)

(mySQL에는 시퀀스가 없고 컬럼에 auto increment(자동증가)를 설정합니다.)

 

--시퀀스 생성
CREATE SEQUENCE board_idx_seq;

--데이터 샘플 추가
INSERT INTO freeboard (idx,name,password,subject,content)
VALUES (board_idx_seq.nextval,'이하니','1111','알립니다.','오늘 모임 변경안내입니다.');
INSERT INTO freeboard (idx,name,password,subject,content)
VALUES (board_idx_seq.nextval,'최사나','2222','공지','공지공지');
INSERT INTO freeboard (idx,name,password,subject,content)
VALUES (board_idx_seq.nextval,'박모모','1234','하이','하이하이!!');
INSERT INTO freeboard (idx,name,password,subject,content)
VALUES (board_idx_seq.nextval,'김땡땡','1111','이벤트','이벤트 안내입니다.');
INSERT INTO freeboard (idx,name,password,subject,content)
VALUES (board_idx_seq.nextval,'박세리','2222','재공지','재공지 재공지');
INSERT INTO freeboard (idx,name,password,subject,content)
VALUES (board_idx_seq.nextval,'한아름','1234','정회원 공지','정회원 안내입니다.');

시퀀스를 1씩 증가시켜 데이터를 추가합니다.

 

데이터 정렬하기

1. 게시물의 목록을 최신글부터 출력하기 위해 역순으로 조회합니다.

SELECT * FROM freeboard ORDER BY idx DESC;

실행 결과

 

2. ROWNUM 키워드로 실행된 결과에 순번을 부여합니다.

SELECT ROWNUM AS R, T.* FROM 
(SELECT * FROM freeboard ORDER BY idx DESC) T;

실행 결과

 

* ROWNUM

조회된 순서대로 순번을 부여합니다.

먼저 정렬시킨 다음에 ROWNUM 키워드를 사용합니다.

 

3. 한 페이지에 출력할 글의 개수만큼을 조건식에 BETWEEN~AND를 사용하여 조회합니다.

SELECT * FROM (
SELECT rownum AS R, T.* FROM 
(SELECT * FROM freeboard ORDER BY idx DESC) T )
--WHERE R BETWEEN 1 AND 10;		--페이지 1에 대한 sql
--WHERE R BETWEEN 11 AND 20; 		--페이지 2에 대한 sql	startNo=(pageNo-1)*10+1
WHERE R BETWEEN 111 AND 120;

실행 결과

4. 글의 총 개수를 COUNT(*) 함수로 출력합니다.

SELECT count(*) FROM freeboard;

실행 결과

 

Spring

사용할 변수 설정

 

Mapper 인터페이스 (FreeboardMapper.java)

public interface FreeboardMapper {
	List<Freeboard> getPageList(Map<String,Integer> map);
	int getCount();
}

getPageList 메소드 : 한 페이지의 글 목록을 List로 리턴합니다.

getCount 메소드 : 작성된 글의 총 개수를 출력합니다.

 

XML 매퍼 파일 (freeboard.xml)

<mapper namespace="com.mycompany.idev.mapper.FreeboardMapper">
	<select id="getPageList" parameterType="Map" resultType="Freeboard">
		SELECT * FROM (
			SELECT rownum AS R, T.* FROM 
				(SELECT * FROM freeboard ORDER BY idx DESC) T )
		WHERE R BETWEEN #{startNo} AND #{endNo}
	</select>
	<select id="getCount" resultType="int">
	SELECT count(*) FROM freeboard
	</select>
</mapper>

 

Model (Freeboard.java)

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Freeboard {
	private int idx;
	private String name;
	private	String password;
	private String subject;
	private String content;
	private int readCount;
	private Date wdate;
	private String ip;
	private int commentCount;
}

 

Model (PageDto.java) ★★★

@Data
@NoArgsConstructor
public class PageDto {
	
	private int pageNo;	//현재 페이지
	private int pageSize;	//보통 10 :  한화면에 보이는 글 목록의 글 개수
	private int totalCount;	//전체 글 개수
	
	private int startNo;	//현재 페이지 글 목록의 시작 번호
	private int endNo;	//현재 페이지 글 목록의 마지막 번호 : startNo+pageSize-1
	private int startPage;	//페이지 이동 버튼의 시작 번호
	private int endPage;	//페이지 이동 버튼의 마지막 번호
	private int totalPage;
	
	public PageDto(int pageNo,int pageSize, int totalCount) {
		//this.pageNo = pageNo;
		this.pageSize = pageSize;
		this.totalCount = totalCount;
	//계산 시작 : 페이지 개수
	totalPage = (totalCount - 1)/pageSize + 1;
	
	//*pageNo는 현재 페이지가 잘못된 값이 전달되었을 때 : 1보다 작은 값 또는 totalPage보다 큰 값
	this.pageNo = (pageNo<1)? 1:pageNo;
	this.pageNo = (pageNo>totalPage)? totalPage:pageNo;
	
	startNo = (this.pageNo-1)*pageSize + 1;
	endNo = startNo + (pageSize - 1);		//*totalCount 이하의 값이어야 합니다.
	this.endNo = this.endNo>totalCount? totalCount:this.endNo;
	
	startPage = (this.pageNo - 1)/10*10 + 1;	//pageNo가 11~20 일 때 startPage는 모두 11
	endPage = startPage + 9;			//*totalPage 이하의 값이어야 합니다.
	this.endPage = this.endPage>totalPage? totalPage:this.endPage;
	}
}

커스텀 생성자에 프로퍼티 계산을 추가합니다.

 

View (list.jsp)

<div style="margin:auto;">
 <table>
 	<tr><th width="10%">번호</th>
 		<th width="45%">제목</th>
 		<th width="15%">작성자</th>
 		<th width="10%">조회수</th>
 		<th width="20%">작성일</th></tr>
 	<c:forEach var="vo" items="${list}">
	<tr>
		<td>${vo.idx }</td> 	
 		<td><a href="detail?idx=${vo.idx}&pageNo=${page.pageNo}" class="title">${vo.subject }</a>
 		...<span style="color:orange;font-size: 80%;">(${vo.commentCount})
 		</span></td>
 		<td>${vo.name }</td>
 		<td>${vo.readCount }</td>
 		<td>
 		<fmt:formatDate value="${vo.wdate }" pattern="yyyy-MM-dd"/>  <!-- 출력패턴 -->
 		</td>
 	</tr>
 	</c:forEach>
 	<tr><td colspan="4">Go!
		<!-- a태그 url요청 get 메소드 -->
		<a class="button" href="insert?pageNo=${page.pageNo }">글쓰기</a>
		<a class="button" href="${pageContext.request.contextPath }">홈</a></td>
		<td>작성글 총 개수 : ${page.totalCount}</td>
 	</tr>
 </table>
</div>

Controller에서 전달 받은 list 애트리뷰트를 forEach문을 이용하여 필요한 프로퍼티들을 출력합니다.

Controller에서 전달 받은 page 애트리뷰트의 필요한 프로퍼티들을 출력합니다.

JSTL fmt태그의 pattern 속성으로 날짜의 형식을 지정합니다.

${pageContext.request.contextPath}로 홈)로 이동합니다.

* contextPath : 현재 프로젝트의 URL

 

Controller (FreeboardController.java)

@Controller
@RequestMapping("/community")
public class FreeboardController {
	@Autowired
	FreeboardMapper mapper;
	
	@RequestMapping("/list")
	public String list(@RequestParam(required=false, defaultValue = "1")
						int pageNo,Model model) {
		PageDto page = new PageDto(pageNo,10,mapper.getCount());
		
		Map<String,Integer> map = new HashMap<>();
		map.put("startNo", page.getStartNo());
		map.put("endNo", page.getEndNo());
		List<Freeboard> list = mapper.getPageList(map);
		
		model.addAttribute("page",page);
		model.addAttribute("list",list);
		
		return "community/list";
	}
}

@RequestParam

→ required 속성값을 false로 하면 파라미터가 없어도 오류 페이지가 나타나지 않습니다.

→ defaultValue 속성값을 설정하면 파라미터가 없을 때 기본값을 설정할 수 있습니다.

Map 객체에 startNo, endNo 값을 설정하여 getPageList 메소드의 매개변수로 사용합니다.

Model 객체로 page, list 애트리뷰트를 전달합니다. 

 

 

 

* Locale 객체

국가 언어 정보를 담고 있는 객체입니다.

 

 

반응형

댓글