댓글과 댓글 수에 대한 처리
tbl_reply 테이블에 insert하고, tb1_board 테이블에는 댓글의 수를 의미하는 replyCnt라는 칼럼을 추가해서 해당 게시물 댓글의 수를 update 한다.
tb1_board 테이블에는 replyCnt 칼럼을 추가
alter table tb1_board add (replycnt number default 0);
|
cs |
기존의 댓글에 존재했다면 replyCnt에 반영해 두어야 하므로 아래의 쿼리를 실행한다.
update tb1_board set replycnt = (select count(rno) from tbl_reply
where tbl_reply.bno = tb1_board.bno);
|
cs |
20.1 프로젝트 수정
데이터베이스가 수정 되었으므로 BoardVO 클래스, MyBatis의 SQL, BoardService를 수정한다.
- BoardVo
package org.zerock.domain;
import java.util.Date;
import lombok.Data;
@Data
public class BoardVO {
private Long bno;
private String title;
private String content;
private String writer;
private Date regdate;
private Date updateDate;
private int replyCnt;
}
|
cs |
- BoardMapper 인터페이스
package org.zerock.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
//import org.apache.ibatis.annotations.Select;
import org.zerock.domain.BoardVO;
import org.zerock.domain.Criteria;
public interface BoardMapper {
// @Select("select * from tb1_board where bno >0")
public List<BoardVO> getList();
public List<BoardVO> getListWithPaging(Criteria cri);
public void insert(BoardVO board);
public void insertSelectKey(BoardVO board);
public BoardVO read (Long bno);
public int delete (Long bno);
public int update(BoardVO board);
public int getTotalCount(Criteria cri);
public void updateReplyCnt(@Param("bno")Long bno, @Param("amount")
int amount);
}
|
cs |
- 새로 추가된 updateReplyCnt( )는 해당 게시물의 번호인 bno와 증가나 감소를 의미하는 amount 변수에 파라미터를 받을 수 있도록 처리한다. 댓글이 등록하면 1이 증가하고, 삭제 되면 1이 감소하기 때문이다.
- MyBatis와 SQL 을 처리하기 위해서는 기본적으로 하나의 파라미터 타입을 사용하기 때문에 위와 같이 2개 이상의 데이터를 전달하려면 @Param이라는 어노테이션을 이용해서 처리할 수 있다.
- BoardMapper.xml
<update id="updateReplyCnt">
update tbl_board set replycnt = replycnt + #{amount} where bno = #{bno}
</update>
<select id="getListWithPaging"
resultType="org.zerock.domain.BoardVO">
<![CDATA[
select
bno, title, content, writer, regdate, updateDate, replycnt
from
(
select /*+INDEX_DESC(tb1_board pk_board) */
rownum rn, bno, title, content, writer, regdate, updateDate, replycnt
from
tb1_board
where
]]>
<include refid="criteria"></include>
<![CDATA[
rownum<= #{pageNum} * #{amount}
)
where rn > (#{pageNum}-1) * #{amount}
]]>
</select>
|
cs |
- ReplyServiceImpl의 트랜잭션 처리
- ReplyServiceImpl 클래스는 기존에는 ReplyMapper만을 이용했지만, 반정규화 처리가 되면서 BoardMapper를 같이 이용해야 하는 상황이 되었다.
- ReplyServiceImpl에서 새로운 댓글이 추가되거나 삭제되는 상황이 되면 BoardMapper와 ReplyMapper 를 같이 이용해서 처리하고, 이 작업은 트랜잭션으로 처리되어야 한다.
package org.zerock.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zerock.domain.Criteria;
import org.zerock.domain.ReplyPageDTO;
import org.zerock.domain.ReplyVO;
import org.zerock.mapper.BoardMapper;
import org.zerock.mapper.ReplyMapper;
import lombok.Setter;
import lombok.extern.log4j.Log4j;
@Service
@Log4j
public class ReplyServiceImpl implements ReplyService {
@Setter(onMethod_ = @Autowired )
private ReplyMapper mapper;
@Setter(onMethod_ =@Autowired)
private BoardMapper boardMapper;
@Transactional
@Override
public int register(ReplyVO vo) {
log.info("register......" + vo);
boardMapper.updateReplyCnt(vo.getBno(), 1);
return mapper.insert(vo);
}
@Override
public ReplyVO get(Long rno) {
log.info("get......" + rno);
return mapper.read(rno);
}
@Override
public int modify(ReplyVO vo) {
log.info("modify......" + vo);
return mapper.update(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);
}
@Override
public List<ReplyVO> getList(Criteria cri, Long bno) {
log.info("get Reply List of a Board " + bno);
return mapper.getListWithPaging(cri, bno);
}
@Override
public ReplyPageDTO getListPage(Criteria cri, Long bno) {
return new ReplyPageDTO(
mapper.getCountByBno(bno),
mapper.getListWithPaging(cri, bno));
}
}
|
cs |
- 기존과 달라지는 점은 기존에는 ReplyMapper만을 주입하기 때문에 자동주입을 이용할 수 있었지만, 추가적으로 BoardMapper를 이용하면서 자동 주입 대신 @Setter를 통한 주입이 이루어지는 점이다.
- 댓글 등록의 경우에 파라미터로 전달받은 ReplyVO 내에 게시물의 번호가 존재하므로 이를 이용해서 댓글을 추가한다.
- 댓글의 삭제는 전달되는 파라미터가 댓글의 번호인 rno만을 받기 때문에 해당 댓글의 게시물을 알아내는 과정이 필요하다. (게시물의 번호를 받으려면 ReplyController까지 같이 수정해야 한다.)
- 화면 수정 - list.jsp
- 게시물의 목록 화면에서 댓글의 숫자가 출력될 수 있도록 수정한다.
<c:forEach items="${list}" var="board">
<tr>
<td><c:out value="${board.bno }" /></td>
<td><a class='move' href='<c:out value ="${board.bno}"/>'>
<c:out value="${board.title }" /> <b>[ <c:out value="${board.replyCnt}" />]</b>
</a>
</td>
<td><c:out value="${board.writer }" /></td>
<td><fmt:formatDate value="${board.regdate }" pattern="yyyy-MM-dd" /></td>
<td><fmt:formatDate value="${board.updateDate }" pattern="yyyy-MM-dd" /></td>
</tr>
</c:forEach>
|
cs |
출처 ; 코드로 배우는 스프링 웹 프로젝트[구멍가게 코딩단]