댓글이 10개를 초과한다면, 댓글을 다음 페이지로 넘기는 처리를 해볼 것이다.
그 작업을 위해 일단 1페이지에 댓글이 10개까지만 보이도록 할 것이므로, 확인해보기 위해 한 게시글에 댓글이 10개 이상 있어야 한다.
그러므로 페이지에서 댓글을 10개가 초과할 때 까지 추가한다.
댓글목록 조회 인덱스 설계
댓글 목록이 'bno'가 기준이 되어야 하므로, 데이터의 양이 많아졌을 때 성능이 저하되는 것을 고려하여 'bno'를 기준으로 하는 인덱스를 먼저 설계해야 한다.
replyMapper.xml 에서 id가 getListWithPaging 인 select를 수정한다.
<select id="getListWithPaging"
resultType="kr.icia.domain.ReplyVO">
select rno, bno, reply, replyer, replydate, updatedate
from
<![CDATA[
(select /*+INDEX(tbl_reply idx_reply)*/
rownum rn, rno, bno, reply, replyer, replyDate, updatedate
from tbl_reply
where bno=#{bno}
and rno > 0
and rownum <= #{cri.pageNum} * #{cri.amount}
order by rno
) where rn > (#{cri.pageNum}-1) * #{cri.amount}
]]>
</select>
쿼리문이 정상 작동하는지 테스트해보기 위해
ReplyMapperTests.java 에서 기존 Test 코드는 주석처리하고 새로운 Test코드를 작성한다.
@Test
public void testList2() {
Criteria cri = new Criteria(2,10);
List<ReplyVO> replies = mapper.getListWithPaging(cri, 800L);
replies.forEach(reply->log.info(reply));
}
800번 게시글의 댓글 2페이지를 출력하도록 작성했다.
JUnit 테스트를 구동해 보면, 콘솔에 다음과 같이 보여지는 것을 볼 수 있다.
서버 구동 후 확인해보면, 댓글이 10개 이상인 게시글에서 댓글이 10개까지만 보여지는 것을 확인할 수 있다.
특정 게시물의 전체 댓글 개수 조회
댓글을 페이징처리하기 위해서 해당 게시물의 전체 댓글의 숫자를 파악해서 화면에 보여줄 필요가 있다.
ReplyMapper.java 에 메소드의 원형을 추가한다.
public int getCountByBno(Long bno); //게시물별 댓글 총개수 파악
ReplyMapper.xml 에서는 id속성값이 getCountByBno인 <select>를 추가한다.
<!-- 게시물별 댓글 총 개수 리턴 -->
<select id="getCountByBno" resultType="int">
select count(rno) from tbl_reply where bno=#{bno}
</select>
댓글 페이징 처리는 댓글 목록과 함께 전체 댓글의 수를 같이 전달해야 한다.
댓글 페이징에 필요한 정보를 담을 새로운 DTO를 생성한다.
src/main/java > kr.icia.domain > new Class 생성 > name: ReplyPageDTO
package kr.icia.domain;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
@Data
@AllArgsConstructor
@Getter
public class ReplyPageDTO {
private int replyTotalCnt; //댓글의 개수
private List<ReplyVO> list; //댓글의 목록
}
ReplyService 인터페이스와 그의 구현 클래스인 ReplyServiceImp 클래스에 ReplyPageDTO를 반환하는 메소드를 추가할 것이다.
ReplyService 에 추가한다.
//댓글의 목록과 게시물의 개수
public ReplyPageDTO getListPage(Criteria cri, Long bno);
ReplyServiceImp 에 추가한다.
@Override
public ReplyPageDTO getListPage(Criteria cri, Long bno) {
//각각의 매퍼를 이용하여 댓글의 개수와 댓글의 목록을 추출
return new ReplyPageDTO(mapper.getCountByBno(bno), mapper.getListWithPaging(cri, bno));
}
이제 생성된 메소드를 호출할 것이다.
ReplyController 에 댓글 목록 가져오기 부분을 수정한다.
// 댓글 목록 가져오기
@GetMapping(value = "/pages/{bno}/{page}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ReplyPageDTO> getList(@PathVariable("page") int page, @PathVariable("bno") Long bno) {
// @PathVariable: url로 넘겨받은 값을 이용
log.info("getList......");
Criteria cri = new Criteria(page, 10);
log.info(cri);
return new ResponseEntity<>(service.getListPage(cri, bno), HttpStatus.OK);
// T<List<ReplyVO>> t = new T<>();
// 댓글 목록을 출력하고, 정상처리 상태를 return함
}
기존과 동일하게 JSON 데이터를 전송하지만 ReplyPageDTO 객체를 JSON으로 전송 하게 되므로, 특정 게시물의 댓글 목록을 조회하면 아래와 같이 'replyCnt'와 list'라는 이름의 속성을 가지는 JSON 문자열이 전송된다.
총 개수를 콘솔에 표시하기
reply.js 에서 '댓글 목록 가져오기'부분의 콜백을 주석처리한다.
그 아래에 코드를 추가한다.
//callback(data); //댓글 목록만 가져오는 경우
callback(data.replyTotalCnt, data.list); //댓글 숫자와 목록을 가져오는 경우
reply.js 를 이용해서 댓글의 페이지를 호출하는 부분은 showList 함수이므로, 페이지번호를 출력하도록 수정해야 한다.
get.jsp 에서 function showList() 를 수정한다.
function showList(page){
replyService.getList({
...
function(list) {
...
})
}
기존에는 list만 받았는데, 이제 replyTotalCnt도 받을 수 있도록 추가하고, 펑션 안에 코드를 추가한다.
function(replyTotalCnt, list) {
console.log("replyCnt : " + replyTotalCnt);
if (page == -1) {
pageNum = Math.ceil(replyTotalCnt / 10.0);
//페이지 번호가 음수라면, 댓글의 마지막 페이지 구하기
showList(pageNum);
return;
}
showlist()는 파라미터로 전달되는 page변수를 이용해서 원하는 댓글 페이지를 가져오게 된다.
이 때, page 번호가 '-1'로 전달되면 마지막 페이지를 찾아서 다시 호출하게 된다.
사용자가 새로운 댓글을 추가하면 showList(-1);을 호출하여 우선 전체 댓글의 숫자를 파악하게 하고, 다시 마지막 페이지를 호출해서 이동시키는 방식으로 동작시킨다.
그러기 위해 방금 수정한 showList 펑션 맨 아래 부분의 showList(1)을 showList(-1)으로 바꾸어준다.
function showList(page){
...
}
showList(-1);
서버 구동 후, 콘솔에 댓글의 총 개수가 표시되고 있다.
또한, 게시글 읽기 페이지에서 댓글은 마지막 페이지를 보여주게 된다.
댓글 페이지번호 화면에 나타내기
댓글의 마지막 페이지를 보여주는 단계까지 완료했다.
그럼 이제 이전 댓글 페이지도 볼 수 있도록 페이지 버튼을 만들어야 한다.
get.jsp의 스크립트에서 showList() 메소드 안에 showReplyPage() 호출 부분을 추가한다.
function showList(page){
replyService.getList({
...
showReplyPage(replyTotalCnt);
})
}
호출한 함수를 구현한다. (showList() 아래에)
/* 댓글 페이징 시작 */
var pageNum = 1;
var replyPageFooter = $(".panel-footer");
function showReplyPage(replyCnt) {
var endNum = Math.ceil(pageNum/10.0) * 10;
//pageNum이 1이라고 가정하면 Math.ceil(1/10.0)*10 을 하면 endNum이 10이 나온다
var startNum = endNum - 9;
var prev = startNum != 1; //startNum이 1이 아니라면 prev가 만들어진다
var next = false;
if (endNum * 10 >= replyCnt) {
endNum = Math.ceil(replyCnt / 10.0);
}
if (endNum * 10 < replyCnt) {
next = true;
}
var str = "<ul class='pagination";
str+= " justify-content-center'>";
if (prev) {
str += "<li class='page-item'><a ";
str += "class='page-link' href='";
str += (startNum -1);
str += "'>이전</a></li>";
}
for (var i = startNum; i <= endNum; i++) {
var active = pageNum == i ? "active" : "";
str += "<li class='page-item " + active
+"'><a class='page-link' ";
str += "href='" + i + "'>" + i + "</a></li>";
}
if (next) {
str += "<li class='page-item'>";
str += "<a class='page-link' href='";
str += (endNum + 1) + "'>다음</a></li>";
}
str += "</ul>";
console.log(str);
replyPageFooter.html(str);
}
/* 댓글 페이징 끝 */
댓글 페이지 번호가 나오는 것 까지는 성공했다.
하지만 아직 페이지 이동은 정상적으로 되지 않는다.
댓글 페이지 이동 처리
이제 페이지 번호를 클릭했을 때 페이지가 이동되도록 처리할 것이다.
get.jsp 스크립트에 추가한다.
//댓글 페이지번호 클릭시 이동 처리
replyPageFooter.on("click", "li a", function(e) {
e.preventDefault();
var targetPageNum = $(this).attr("href");
pageNum = targetPageNum;
showList(pageNum);
});
1번 페이지를 누르면 페이지가 정상적으로 이동된다.
댓글 개수를 목록에서 제목 옆에 표시하기
해당 게시글에 댓글이 있으면 댓글 개수를 목록에서도 확인할 수 있도록 해볼 것이다.
먼저, tbl_board에 리플 개수 컬럼을 추가하기 위해
sql developer 의 admin 계정으로 접속하여 다음 쿼리문을 작성한다.
ALTER TABLE tbl_board ADD (
replycnt NUMBER DEFAULT 0
);
--게시물 테이블에 replycnt 컬럼을 추가하면서 초기값은 0으로 설정
UPDATE tbl_board
SET
replycnt = (
SELECT
COUNT(rno)
FROM
tbl_reply
WHERE
tbl_reply.bno = tbl_board.bno
);
--게시판의 replycnt에 댓글 테이블의 게시물별 총 댓글 개수를 계산하여 replycnt에 적용
COMMIT;
tbl_board 에 replycnt 컬럼이 추가되었고 댓글의 수가 잘 표시되고 있다.
BoardVO.java 를 열어 replycnt를 추가한다. (다시말하지만, mybatis를 이용해 게터와 세터는 자동 생성하고 있다)
private int replyCnt;
댓글이 추가될 때마다 댓글의 개수를 업데이트해야 하므로,
BoardMapper.java 에 추가한다.
public int updateReplyCnt(@Param("bno") Long bno, @Param("amount") int amount);
BoardMapper.xml 에서 id 속성값이 getListWithPaging 인 곳을 찾아 select 문에 replycnt를 추가한다.
댓글이 추가되거나 삭제되면 댓글의 총 개수가 변화해야하므로 이 부분을 구현해볼 것이다.
update 속성값을 가진 코드를 추가한다.
<update id="updateReplyCnt">
update tbl_board set replycnt = replycnt + #{amount}
where bno = #{bno}
</update>
ReplyServiceImp.java 에 BoardMapper를 명시해준다.
@Setter(onMethod_ = @Autowired)
private BoardMapper boardMapper;
그리고 register와 remove 부분을 각각 아래와 같이 수정한다.
@Transactional
@Override
public int register(ReplyVO vo) {
log.info("register......" + vo);
boardMapper.updateReplyCnt(vo.getBno(), 1);
//댓글이 등록된다면 게시물 테이블의 댓글 총개수가 1증가
return mapper.insert(vo);
}
@Transactional
@Override
public int remove(Long rno) {
log.info("remove......" + rno);
ReplyVO vo = mapper.read(rno);
boardMapper.updateReplyCnt(vo.getBno(), -1);
return mapper.delete(rno);
}
@Transactional Refereunce ▶ [Spring] @Transactional 사용시 주의해야할 점 :: 개발자로 홀로 서기 (tistory.com)
list.jsp 에서 목록에 게시글이 표시되는 부분을 추가할 것이다.
빨간색으로 표시된 부분을 나누어 사이에 코드를 입력한다.
<c:if test="${board.replyCnt ne 0 }">
<span style="color:red;">[<c:out value="${board.replyCnt }"/>]</span>
</c:if>
댓글의 개수가 표시되며, 새 댓글을 작성하거나 삭제하면 숫자가 변경된다.
댓글 수정/삭제 후 현재 댓글 페이지 유지하기
댓글을 수정/삭제한 후에 페이지가 풀리는 것을 보완하기 위해 get.jsp에서 댓글 수정 부분과 삭제 부분의 스크립트를 일부 수정한다.
showList(-1) 부분을 showList(pageNum)으로 변경하기만 하면 된다.
'개발입문 > SPRING 게시판 만들기' 카테고리의 다른 글
[SPRING] 첨부파일 다운로드 및 수정/삭제 (0) | 2022.10.14 |
---|---|
[SPRING] 첨부파일 업로드 (0) | 2022.10.14 |
[SPRING] 댓글 화면 처리 및 CRUD (0) | 2022.10.13 |
[SPRING] 댓글 기능 구현 (0) | 2022.10.13 |
[SPRING] 검색 기능 구현 (0) | 2022.10.13 |
댓글