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>