Spring 게시판 만들기

Spring - 14 (댓글 페이징)

단데기이 2022. 4. 26. 13:52
728x90

댓글 페이징 쪽번호를 만들어본다.

get.jsp

       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; // false = (1 != 1)
            var next = false;
            // replyCnt : 384, endNum : 39
            if(endNum * 10 >= replyCnt) { // 100 >= 384
                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);
        }
        // 덧글 페이징 끝

showlist함수부분 스크립트에 위에 만든 showReplyPage(replyTotalCnt); 를 추가한다.

		var replyUL = $(".chat");
		
		function showList(page) {
			replyService.getList({
				bno : bnoValue,
				page : page || 1
			}, function(replyTotalCnt, list) {
					console.log("댓글갯수 : " + replyTotalCnt);
					
					if(page == -1){
						pageNum = Math.ceil(replyTotalCnt / 10.0);
						
						showList(pageNum);
						
						return;
					}
					
					var str = "";
					
					if(list ==null || list.length == 0){
						replyUL.html("");
						return;
					}
				
				for (var i = 0, len = list.length || 0; i<len; i++){
					str += "<li class='left ";
					str += "clearfix' data-rno='";
					str += list[i].rno+"'>";
					str += "<div><div class='header' ";
					str += "><strong class='";
					str += "primart-font'>";
					str += list[i].replyer+ "</strong>";
					str += "<small class='float-sm-right '>";
					str += replyService.displayTime(list[i].replyDate)
					+ "</small></div>";
					str += "<p>" + list[i].reply;
					str += "</p></div></li>";
				}
				replyUL.html(str); 
				showReplyPage(replyTotalCnt);
			});
		}
		showList(1);

외관을 만들었으니 이제 클릭했을때 해당 덧글 목록이 보이도록 변경한다.

// 덧글 페이징 클릭시 처리.
        replyPageFooter.on("click", "li a", function(e){
        	e.preventDefault();
        	var targetPageNum = $(this).attr("href");
        	pageNum = targetPageNum;
        	showList(pageNum);
        });

 

 

게시물에 댓글 개수 출력하기

해당 게시물에 댓글이 몇개가 달렸는지 알 수 있게한다.

 

sqldeveloper에서 쿼리 실행

alter table tbl_board add (replycnt number default 0);
-- 게시물 테이블에 replycnt 컬럼을 추가 하면서 초기값은 9으로 설정.
update tbl_board set replycnt=(select count(rno) from tbl_reply
where tbl_reply.bno=tbl_board.bno);
-- 게시판의 replycnt에 덧글 테이블의 게시물별 덧글 총갯수를 계산하여
-- replycnt 에 적용.
commit;

 

domain패키지의 BoardVO에 아래 필드값을 추가한다.

private int replyCnt;

 

BoardMapper 인터페이스에 원형 메서드를 추가한다.

public void updateReplyCnt(@Param("bno") Long bno, @Param("amount") int amount);


BoardMapper.xml 에서 getListWithPaging을 수정한다. (replycnt 를 추가하였다)

<select id="getListWithPaging" resultType="kr.icia.domain.BoardVO">
    <![CDATA[
    select bno, title, content, writer, regdate, 
    updatedate, replycnt from
    (select /*+INDEX_DESC(tbl_board pk_board) */ 
    rownum rn, bno, title, content, writer, regdate, 
    updatedate, replycnt from tbl_board 
    where 
    ]]>
    <include refid="criteria"/>
    <![CDATA[
    rownum <= #{pageNum} * #{amount}) 
    where rn > (#{pageNum}-1) * #{amount}
    ]]>
</select>

updateReplyCnt 쿼리를 추가한다.

<update id="updateReplyCnt">
update tbl_board set replycnt=replycnt + #{amount}
where bno=#{bno}
</update>


ReplyServiceImpl 클래스에서 BoardMapper도 자동 초기화 처리를 추가해준다.

@Setter(onMethod_ = @Autowired)
private BoardMapper boardMapper;
// 게시물 테이블과 덧글 테이블은 동시에 동작하거나 취소 되어야 함.
// @Transactional 이용.

그 아래로 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);
	}

 

이제 list.jsp 에서 게시물 제목 옆에 덧글수를 표시해준다.

				<tbody>
					<c:forEach var="board" items="${list }">
					<!-- items : boardVO 객체 여러개의 배열 -->
						<tr>
							<td><c:out value="${board.bno }"></c:out></td>
							<td><a href="${board.bno }" class="move"><c:out
										value="${board.title }"/>
										<!-- JSTL문법 != 을 ne로 표시한것  / == eq -->
										<c:if test="${board.replyCnt ne 0 }">
										<span style="color:red;">[
										<c:out value="${board.replyCnt }"/>]</span>
										</c:if>
										</a></td>
							<td><c:out value="${board.writer }"></c:out></td>
							<td><fmt:formatDate pattern="yyyy-MM-dd"
									value="${board.regdate }" /></td>
							<td><fmt:formatDate pattern="yyyy-MM-dd"
									value="${board.updateDate }" /></td>
						</tr>
					</c:forEach>
				</tbody>

댓글 추가 또는 삭제시 즉시 갯수에 반영되도록 ReplyServiceImpl에 코드를 추가한다.

	@Override
	public int register(ReplyVO vo) {
		log.info("register......" + vo);
		boardMapper.updateReplyCnt(vo.getBno(), 1);
		// 덧글이 등록 된다면, 게시물 테이블의 덧글 총갯수 1증가.
		
		return mapper.insert(vo);
	}
	@Override
	public int remove(Long rno) {
		log.info("삭제 " + rno);
		ReplyVO vo = mapper.read(rno);
		boardMapper.updateReplyCnt(vo.getBno(), -1);
		return mapper.delete(rno);
	}

 

 

※ ReplyMapper.xml 에서 getWithPaging이 인덱스 idx_reply이 있다고 착각하여 댓글 순서가 제대로 반영안됨

원래대로라면 인덱스 자체에서 rno로 자동으로 정렬되서 출력될것이다.

때문에 idx_reply를 pk_reply로 변경해주고 order by 절은 삭제해 주면 해결된다.

 

수정전

<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>

수정후

<select id="getListWithPaging"
    resultType="kr.icia.domain.ReplyVO">
    select rno, bno, reply, replyer, replydate, updatedate
    from
    <![CDATA[
    (select /*+INDEX(tbl_reply pk_reply) */
    rownum rn, rno, bno, reply,replyer,replyDate, updatedate
    from tbl_reply
    where bno=#{bno}
    and rno > 0
    and rownum <= #{cri.pageNum} * #{cri.amount}
    ) where rn > (#{cri.pageNum}-1)* #{cri.amount}
    ]]>
</select>