오늘은 댓글 목록 기능을 구현해보고자 한다.
게시글을 조회할 때 아래에 댓글 창도 뜨도록 구현할 예정이다.
오랜만에 블로그 글을 쓰는 거 같다 ㅎㅎ...
댓글 테이블을 새로 만들어줘야 한다. 그리고 댓글의 경우 독립적인 것이 아닌 특정 게시물에 종속된 형태이기 때문에 게시물을 구분할 수 있어야 한다. 이때 사용되는 것이 게시물 번호인 id이다. 또한 댓글 구분에 필요한 댓글번호 (rid)도 만들어준다.
댓글은 게시물이 있어야 작성할 수 있기에 댓글 테이블의 id는 기존 게시판 테이블의 id를 따라가야 한다. 그러므로 이를 참조하기 위해 foreign key를 사용한다.
foreign key는 대상 테이블의 컬럼과 참조하는 테이블의 컬럼값이 존재하는지 확인하고, 참조하는 테이블의 값이 없을 경우 에러를 발생시킨다.
DROP TABLE if EXISTS board_reply;
create table board_reply (
`RID` INT NOT NULL AUTO_INCREMENT,
`ID` INT NOT NULL ,
`CONTENT` varchar(1000) not null,
`WRITER` varchar(50) not null,
`USERPASS` VARCHAR(20) NOT NULL,
`CREATE_DATE` timestamp default NOW(),
PRIMARY KEY( `RID`, `ID`)
);
alter table BOARD_REPLY add constraint board_reply_id foreign key(ID)
references BOARD_TABLE(ID);
commit;

그러면 board_reply가 정상적으로 생성된 것을 확인할 수 있다.
게시글의 댓글 쿼리가 제대로 작동되는지 HeidiSQL에서 테스트해보자.
테스트 데이터를 넣기 전에 게시판 데이터 베이스에 가서 ID 값이 존재하는지 확인해본다.

게시판 테이블인 board_table의 ID가 위와 같을 때 12번 ID값을 갖는 게시물에 댓글을 추가해보자.
INSERT INTO board_reply(ID, CONTENT, WRITER, USERPASS)
VALUES(12, '댓글 테스트 내용', '홍길동', 1234);
SELECT * FROM board_reply
WHERE ID = 12;

그러면 정상적으로 ID가 12인 댓글 데이터를 얻어오는 것을 확인할 수 있다.
테스트하면서 AUTO_INCREMENT를 초기화해줘야 할 때가 있는데
ALTER TABLE board_reply AUTO_INCREMENT = 1;
명령어를 사용하면 된다. 다만 해당 쿼리문을 실행하기 전에 테이블의 데이터는 전부 비워진 상태여야 한다.
여튼 댓글 데이터가 제대로 삽입되는 것을 확인했으니 스프링으로 가 본격적으로 구현을 시작하자.
com.board.domain에 ReplyVO.java를 새로 생성한 뒤 아래와 같이 코드를 작성한다.

우클릭 > Source > Generate Getters and Setters 속성을 이용하여 getter와 setter까지 생성해준다.
package com.board.domain;
import java.util.Date;
public class ReplyVO {
private int rid;
private int id;
private String content;
private String writer;
private String userpass;
private Date create_date;
public int getRid() {
return rid;
}
public int getId() {
return id;
}
public String getContent() {
return content;
}
public String getWriter() {
return writer;
}
public String getUserpass() {
return userpass;
}
public Date getCreate_date() {
return create_date;
}
public void setRid(int rid) {
this.rid = rid;
}
public void setId(int id) {
this.id = id;
}
public void setContent(String content) {
this.content = content;
}
public void setWriter(String writer) {
this.writer = writer;
}
public void setUserpass(String userpass) {
this.userpass = userpass;
}
public void setCreate_date(Date create_date) {
this.create_date = create_date;
}
@Override
public String toString() {
return "ReplyVO [rid=" + rid + ", id=" + id + ", content=" + content + ", writer=" + writer + ", userpass=" + userpass +", create_date="
+ create_date + "]";
}
}
src/main/resources의 mappers 폴더 안에 replyMapper.xml 파일 생성 후, 댓글을 조회하는 쿼리문을 추가한다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="replyMapper">
<!-- 댓글 조회 -->
<select id="readReply" resultType="com.board.domain.ReplyVO">
SELECT
RID, CONTENT, WRITER, USERPASS, CREATE_DATE
FROM BOARD_REPLY
WHERE ID = #{id}
</select>
</mapper>
이제 com.board.dao 패키지 안에 ReplyDAO.java와 ReplyDAOImpl.java를 새로 생성하여 다음과 같이 코드를 작성해준다.

package com.board.dao;
import java.util.List;
import com.board.domain.ReplyVO;
public interface ReplyDAO {
// View comments
public List<ReplyVO> readReply(int id) throws Exception;
}

package com.board.dao;
import java.util.List;
import javax.inject.Inject;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
import com.board.domain.ReplyVO;
@Repository
public class ReplyDAOImpl implements ReplyDAO {
@Inject
SqlSession sql;
// View post
@Override
public List<ReplyVO> readReply(int id) throws Exception{
return sql.selectList("replyMapper.readReply", id);
}
}
이제 com.board.service 패키지에 ReplyService와 ReplyServiceImpl 을 생성하여 아래와 같이 코드를 작성한다.

package com.board.service;
import java.util.List;
import com.board.domain.ReplyVO;
public interface ReplyService {
public List<ReplyVO> readReply(int id) throws Exception;
}

package com.board.service;
import java.util.List;
import javax.inject.Inject;
import org.springframework.stereotype.Service;
import com.board.dao.ReplyDAO;
import com.board.domain.ReplyVO;
@Service
public class ReplyServiceImpl implements ReplyService{
@Inject
private ReplyDAO dao;
@Override
public List<ReplyVO> readReply(int id) throws Exception{
return dao.readReply(id);
}
}
DAO와 Service까지 구현하였으면 Controller에 추가해주기 위해 BoardController로 이동한다.
BoardController 최상단에 ReplyService 객체를 선언해주고

게시판 조회에 해당하는 read 함수로 가 replyService의 readReply 함수를 호출해준다.

Controller에 기능을 추가하였으면 jsp 파일을 수정하러 가자. 게시판의 내용을 조회하는 readView.jsp로 가서 section 태그 아래에 다음 코드를 추가해준다.

<!-- 댓글 -->
<div id="reply">
<ul class="replyList">
<c:forEach items="${replyList}" var="replyList">
<li>
<p>
작성자 ${replyList.writer}<br />
</p>
${replyList.content}
(<fmt:formatDate value="${replyList.create_date}" pattern="yyyy.MM.dd hh:mm" />)
</li>
</c:forEach>
</ul>
</div>
그러고 서버를 실행하여 12번 게시글을 조회해보면 다음과 같이 댓글이 정상적으로 출력되는 것을 확인할 수 있다. 데이터베이스에서 선언할 때 쓴 비밀번호인 userpass는 추후에 게시판 비밀번호까지 구현할 때 한꺼번에 구현할 예정이다....

melonpeach.tistory.com/34?category=806570 (댓글 목록 기능 구현)
mamoruoppa.tistory.com/67 (mariaDB AUTO_INCREMENT 초기화)
kuzuro.blogspot.com/2019/10/14.html (댓글 테이블 쿼리 생성)
'프로그래밍 > Java' 카테고리의 다른 글
| [Spring] 스프링 삽질일지 8일차 - 댓글 작성 기능, 경고창 팝업, 조회수 기능 (0) | 2021.05.14 |
|---|---|
| [Spring] 스프링 삽질일지 6일차 - 내용 부족 시 경고창 팝업, 페이징 기능 구현(데모) (0) | 2021.05.12 |
| [Spring] 스프링 삽질일지 5일차 - 게시판 목록, 게시판 조회, 게시판 수정 및 삭제 기능 구현(미완성) (0) | 2021.05.04 |
| [Spring] 스프링 삽질일지 4일차 - 게시판 작성 기능 구현(2) (0) | 2021.05.03 |
| [Spring] 스프링 삽질일지 3일차 - 게시판 작성 기능 구현(1) (0) | 2021.05.02 |