
zboard_reply
--댓글
create table zboard_reply(
re_num number not null,
re_content varchar2(900) not null,
re_date date default sysdate not null,
re_modifydate date,
re_ip varchar2(40) not null,
board_num number not null,
mem_num number not null,
constraint zreply_pk primary key (re_num),
constraint zreply_fk1 foreign key (board_num)
references zboard (board_num),
constraint zreply_fk2 foreign key (mem_num)
references zmember (mem_num)
);
create sequence zreply_seq;
package kr.board.vo;
public class BoardReplyVO {
private int re_num; //댓글번호
private String re_content; //내용
private String re_date; //등록일
private String re_modifydate; //수정일
private String re_ip; //아이피주소
private int board_num; //부모글번호
private int mem_num; //작성자 회원번호
private String id; //작성자 아이디
public int getRe_num() {
return re_num;
}
public void setRe_num(int re_num) {
this.re_num = re_num;
}
public String getRe_content() {
return re_content;
}
public void setRe_content(String re_content) {
this.re_content = re_content;
}
public String getRe_date() {
return re_date;
}
public void setRe_date(String re_date) {
this.re_date = re_date;
}
public String getRe_modifydate() {
return re_modifydate;
}
public void setRe_modifydate(String re_modifydate) {
this.re_modifydate = re_modifydate;
}
public String getRe_ip() {
return re_ip;
}
public void setRe_ip(String re_ip) {
this.re_ip = re_ip;
}
public int getBoard_num() {
return board_num;
}
public void setBoard_num(int board_num) {
this.board_num = board_num;
}
public int getMem_num() {
return mem_num;
}
public void setMem_num(int mem_num) {
this.mem_num = mem_num;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
//댓글 등록
public void insertReplyBoard(BoardReplyVO boardReply)
throws Exception{
Connection conn = null;
PreparedStatement pstmt = null;
String sql = null;
try {
//커넥션풀로부터 커넥션 할당
conn = DBUtil.getConnection();
//SQL문 작성
sql = "INSERT INTO zboard_reply (re_num,re_content,"
+ "re_ip,mem_num,board_num) VALUES ("
+ "zreply_seq.nextval,?,?,?,?)";
//PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
//?에 데이터 바인딩
pstmt.setString(1, boardReply.getRe_content());
pstmt.setString(2, boardReply.getRe_ip());
pstmt.setInt(3, boardReply.getMem_num());
pstmt.setInt(4, boardReply.getBoard_num());
//SQL문 실행
pstmt.executeUpdate();
}catch(Exception e) {
throw new Exception(e);
}finally {
DBUtil.executeClose(null, pstmt, conn);
}
}
//댓글 개수
public int getReplyBoardCount(int board_num)
throws Exception{
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = null;
int count = 0;
try {
//커넥션풀로부터 커넥션을 할당
conn = DBUtil.getConnection();
//SQL문
sql = "SELECT COUNT(*) FROM zboard_reply WHERE board_num=?";
//PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
//?에 데이터 바인딩
pstmt.setInt(1, board_num);
//SQL문 실행
rs = pstmt.executeQuery();
if(rs.next()) {
count = rs.getInt(1);
}
}catch(Exception e) {
throw new Exception(e);
}finally {
DBUtil.executeClose(rs, pstmt, conn);
}
return count;
}
//댓글 목록
public List<BoardReplyVO> getListReplyBoard(
int start, int end, int board_num)
throws Exception{
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List<BoardReplyVO> list = null;
String sql = null;
try {
//커넥션풀로부터 커넥션 할당
conn = DBUtil.getConnection();
//SQL문 작성
sql = "SELECT * FROM (SELECT a.*, rownum rnum FROM "
+ "(SELECT * FROM zboard_reply JOIN zmember USING(mem_num) "
+ "WHERE board_num=? ORDER BY re_num DESC)a) "
+ "WHERE rnum >= ? AND rnum <= ?";
//PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
//?에 데이터 바인딩
pstmt.setInt(1, board_num);
pstmt.setInt(2, start);
pstmt.setInt(3, end);
//SQL문 실행
rs = pstmt.executeQuery();
list = new ArrayList<BoardReplyVO>();
while(rs.next()) {
BoardReplyVO reply = new BoardReplyVO();
reply.setRe_num(rs.getInt("re_num"));
reply.setRe_date(rs.getString("re_date"));
reply.setRe_modifydate(
rs.getString("re_modifydate"));
reply.setRe_content(StringUtil.useBrNoHTML(
rs.getString("re_content")));
reply.setBoard_num(rs.getInt("board_num"));
reply.setMem_num(rs.getInt("mem_num"));//작성자 회원번호
reply.setId(rs.getString("id"));//작성자 아이디
list.add(reply);
}
}catch(Exception e) {
throw new Exception(e);
}finally {
DBUtil.executeClose(rs, pstmt, conn);
}
return list;
}
package kr.board.action;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.codehaus.jackson.map.ObjectMapper;
import kr.board.dao.BoardDAO;
import kr.board.vo.BoardReplyVO;
import kr.controller.Action;
public class WriteReplyAction implements Action{
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
Map<String,String> mapAjax =
new HashMap<String,String>();
HttpSession session = request.getSession();
Integer user_num =
(Integer)session.getAttribute("user_num");
if(user_num==null) {//로그인이 되지 않은 경우
mapAjax.put("result", "logout");
}else {//로그인이 된 경우
//전송된 데이터 인코딩 타입 지정
request.setCharacterEncoding("utf-8");
//자바빈(VO)을 생성해서 전송된 데이터 저장
BoardReplyVO reply = new BoardReplyVO();
reply.setMem_num(user_num);//댓글 작성자 회원번호
reply.setRe_content(request.getParameter("re_content"));
reply.setRe_ip(request.getRemoteAddr());
reply.setBoard_num(Integer.parseInt(
request.getParameter("board_num")));//댓글의 부모 글번호
BoardDAO dao = BoardDAO.getInstance();
dao.insertReplyBoard(reply);
mapAjax.put("result", "success");
}
//JSON 데이터로 변환
ObjectMapper mapper = new ObjectMapper();
String ajaxData = mapper.writeValueAsString(mapAjax);
request.setAttribute("ajaxData", ajaxData);
return "/WEB-INF/views/common/ajax_view.jsp";
}
}
package kr.board.action;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.codehaus.jackson.map.ObjectMapper;
import kr.board.dao.BoardDAO;
import kr.board.vo.BoardReplyVO;
import kr.controller.Action;
import kr.util.PagingUtil;
public class ListReplyAction implements Action{
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
//전송된 데이터 인코딩 타입 지정
request.setCharacterEncoding("utf-8");
String pageNum = request.getParameter("pageNum");
if(pageNum==null) {
pageNum = "1";
}
String rowCount = request.getParameter("rowCount");
if(rowCount==null) {
rowCount = "10";
}
int board_num = Integer.parseInt(
request.getParameter("board_num"));
BoardDAO dao = BoardDAO.getInstance();
int count = dao.getReplyBoardCount(board_num);
/*
* ajax 방식으로 목록을 표시하기 때문에 PagingUtil은 페이지수 표시가
* 목적이 아니라 목록 데이터의 페이지 처리를 위해 rownum 번호를
* 구하는 것이 목적임
*/
PagingUtil page = new PagingUtil(
Integer.parseInt(pageNum),count,
Integer.parseInt(rowCount));
List<BoardReplyVO> list = null;
if(count > 0) {
list = dao.getListReplyBoard(
page.getStartRow(),page.getEndRow(),
board_num);
}else {
list = Collections.emptyList();
}
HttpSession session = request.getSession();
Integer user_num =
(Integer)session.getAttribute("user_num");
Map<String,Object> mapAjax =
new HashMap<String,Object>();
mapAjax.put("count", count);
mapAjax.put("list", list);
//로그인한 사람이 작성자인지 체크하기 위해서 로그인한 회원번호 전송
mapAjax.put("user_num", user_num);
//JSON 문자열로 변환
ObjectMapper mapper = new ObjectMapper();
String ajaxData = mapper.writeValueAsString(mapAjax);
request.setAttribute("ajaxData", ajaxData);
return "/WEB-INF/views/common/ajax_view.jsp";
}
}
$(function(){
let rowCount = 10;
let currentPage;
let count;
/* ===============================
* 댓글 목록
* =============================== */
//댓글 목록
function selectList(pageNum){
currentPage = pageNum;
//로딩 이미지 노출
$('#loading').show();
//서버와 통신
$.ajax({
url:'listReply.do',
type:'post',
data:{pageNum:pageNum,rowCount:rowCount,board_num:$('#board_num').val()},
dataType:'json',
success:function(param){
//로딩 이미지 감추기
$('#loading').hide();
count = param.count;
if(pageNum==1){
//처음 호출시는 해당 ID의 div의 내부 내용물을 제거
$('#output').empty();
}
$(param.list).each(function(index,item){
let output = '<div class="item">';
output += '<h4>' + item.id + '</h4>';
output += '<div class="sub-item">';
output += '<p>' + item.re_content + '</p>';
if(item.re_modifydate){
output += '<span class="modify-date">최근 수정일 : ' + item.re_modifydate + '</span>';
}else{
output += '<span class="modify-date">등록일 : ' + item.re_date + '</span>';
}
//로그인한 회원번호와 작성자의 회원번호 일치 여부 체크
if(param.user_num == item.mem_num){
output += ' <input type="button" data-renum="' + item.re_num + '" value="수정" class="modify-btn">';
output += ' <input type="button" data-renum="' + item.re_num + '" value="삭제" class="delete-btn">';
}
output += '<hr size="1" noshade width="100%">';
output += '</div>';
output += '</div>';
//문서 객체에 추가
$('#output').append(output);
});
//page button 처리
if(currentPage>=Math.ceil(count/rowCount)){
//다음 페이지가 없음
$('.paging-button').hide();
}else{
//다음 페이지가 존재
$('.paging-button').show();
}
},
error:function(){
$('#loading').hide();
alert('네트워크 오류 발생');
}
});
}
//페이지 처리 이벤트 연결(다음 댓글 보기 버튼 클릭시 데이터 추가)
$('.paging-button input').click(function(){
selectList(currentPage + 1);
});
/* ===============================
* 댓글 등록
* =============================== */
//댓글 등록
$('#re_form').submit(function(event){
if($('#re_content').val().trim()==''){
alert('내용을 입력하세요');
$('#re_content').val('').focus();
return false;
}
//form 이하의 태그에 입력한 데이터를 모두 읽어서 쿼리 스트링으로 반환
let form_data = $(this).serialize();
//서버와 통신
$.ajax({
url:'writeReply.do',
type:'post',
data:form_data,
dataType:'json',
success:function(param){
if(param.result == 'logout'){
alert('로그인해야 작성할 수 있습니다.');
}else if(param.result == 'success'){
//폼 초기화
initForm();
//댓글 작성이 성공하면 새로 삽입한 글을 포함해서 첫 번째
//페이지의 게시글 목록을 다시 호출함
selectList(1);
}else{
alert('댓글 등록 오류');
}
},
error:function(){
alert('네트워크 오류 발생');
}
});
//기본 이벤트 제거
event.preventDefault();
});
//댓글 작성 폼 초기화
function initForm(){
$('textarea').val('');
$('#re_first .letter-count').text('300/300');
}
/* ===============================
* 댓글 수정
* =============================== */
/* ===============================
* 댓글 등록 및 수정 공통
* =============================== */
//textarea에 내용 입력시 글자수 체크
$(document).on('keyup','textarea',function(){
//입력한 글자수 구함
let inputLength = $(this).val().length;
if(inputLength > 300){//300자를 넘어선 경우
$(this).val($(this).val().substring(0,300));
}else{//300자 이하인 경우
let remain = 300 - inputLength;
remain += '/300';
if($(this).attr('id') == 're_content'){
//등록폼 글자수
$('#re_first .letter-count').text(remain);
}else{
//수정폼 글자수
$('#mre_first .letter-count').text(remain);
}
}
});
/* ===============================
* 댓글 삭제
* =============================== */
/* ===============================
* 초기 데이터(목록) 호출
* =============================== */
selectList(1);
});
/board/writeReply.do=kr.board.action.WriteReplyAction
/board/listReply.do=kr.board.action.ListReplyAction