프로젝트가 거의 막바지에 다다라서 수업은 오전에 잠깐만 하고 남은 시간은 프로젝트에 전부 썼다.
일단 오늘 한 수업은 문의 게시판 만들기 이다.
package com.sist.vo;
/*
* NO NOT NULL NUMBER
NAME NOT NULL VARCHAR2(34)
SUBJECT NOT NULL VARCHAR2(2000)
CONTENT NOT NULL CLOB
PWD NOT NULL VARCHAR2(10)
REGDATE DATE
HIT NUMBER
GROUP_ID NUMBER
GROUP_STEP NUMBER
GROUP_TAB NUMBER
*/
import java.util.*;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class BoardReplyVO {
private int no, hit, group_id, group_step, group_tab;
private String name, subject, content, pwd;
private Date regdate;
}
테이블을 먼저 만들어 준다. 답변은 하나씩만 달꺼기 때문에 group_id, group_step, group_tab 까지만 컬럼을 만들어 준다.
같은 아이디끼리 붙여서 출력을 해주고, 관리자가 단 답변은 step과 tab에 각각 1을 입력해주면 된다.
먼저 자료실 목록을 출력하는 dao
// 자료실 목록 출력
public List<BoardReplyVO> boardReplyListData(int page)
{
List<BoardReplyVO> list=new ArrayList<BoardReplyVO>();
try
{
getConnection();
String sql="SELECT no,subject,name,regdate,hit,group_tab,num "
+"FROM (SELECT no,subject,name,regdate,hit,group_tab,rownum as num "
+"FROM (SELECT no,subject,name,regdate,hit,group_tab "
+"FROM project_board_reply ORDER BY group_id DESC,group_step ASC)) "
+"WHERE num BETWEEN ? AND ?";
int rowSize=10;
int start=(rowSize*page)-(rowSize-1);
int end=rowSize*page;
ps=conn.prepareStatement(sql);
ps.setInt(1, start);
ps.setInt(2, end);
ResultSet rs=ps.executeQuery();
while(rs.next())
{
BoardReplyVO vo=new BoardReplyVO();
vo.setNo(rs.getInt(1));
vo.setSubject(rs.getString(2));
vo.setName(rs.getString(3));
vo.setRegdate(rs.getDate(4));
vo.setHit(rs.getInt(5));
vo.setGroup_tab(rs.getInt(6));
list.add(vo);
}
rs.close();
}catch(Exception ex)
{
ex.printStackTrace();
}
finally
{
disConnection();
}
return list;
}
list는 출력을 해야하는 부분이기 때문에, 페이지를 나눠주고 order by는 group_id desc로 (입력 최신순), group_step은 asc로 (질문-답변순)으로 잡아주고 출력한다.
페이지를 잡아주고, list에 값을 채워 넣어준 뒤 값을 출력한다.
@RequestMapping("boardreply/list.do")
public String boardreply_list(HttpServletRequest request,HttpServletResponse response)
{
String page=request.getParameter("page");
if(page==null)
page="1";
int curpage=Integer.parseInt(page);
BoardReplyDAO dao=BoardReplyDAO.newInstance();
List<BoardReplyVO> list=dao.boardReplyListData(curpage);
int totalpage=dao.boardReplyTotalPage();
request.setAttribute("list", list);
request.setAttribute("curpage", curpage);
request.setAttribute("totalpage", totalpage);
request.setAttribute("main_jsp", "../boardreply/list.jsp");
return "../main/main.jsp";
}
위에는 listModel
page를 입력받아서 list를 받아온다.
// 총페이지 구하기
public int boardReplyTotalPage()
{
int total=0;
try
{
getConnection();
String sql="SELECT CEIL(COUNT(*)/10.0) FROM project_board_reply";
ps=conn.prepareStatement(sql);
ResultSet rs=ps.executeQuery();
rs.next();
total=rs.getInt(1);
rs.close();
}catch(Exception ex)
{
// 에러 처리
ex.printStackTrace();
}
finally
{
// 반환
disConnection();
}
return total;
}
총페이지 구하는건 이미 많이 했으니 설명 생략
포인트는 ceil 함수를 사용해서 올려주는 것이다.
// insert
public void boardReplyInsert(BoardReplyVO vo)
{
try
{
getConnection();
String sql="INSERT INTO project_board_reply(no,name,subject,content,pwd,group_id) "
+"VALUES((SELECT NVL(MAX(no)+1,1) FROM project_board_reply),?,?,?,?,"
+"(SELECT NVL(MAX(group_id)+1,1) FROM project_board_reply))";
ps=conn.prepareStatement(sql);
ps.setString(1, vo.getName());
ps.setString(2, vo.getSubject());
ps.setString(3, vo.getContent());
ps.setString(4, vo.getPwd());
ps.executeUpdate();
}catch(Exception ex)
{
ex.printStackTrace();
}
finally
{
disConnection();
}
}
글 입력 메소드
시퀀스를 따로 만들지 않아서 그냥 max+1을해서 번호를 지정해 줬는데 나중에 혼자 할때는 꼭 시퀀스를 써주자.
그룹아이디 역시 마찬가지로 max+1을 해줘서 하나씩 올려준다.
@RequestMapping("boardreply/insert_ok.do")
public String boardReply_insert_ok(HttpServletRequest request,HttpServletResponse response)
{
try
{
request.setCharacterEncoding("UTF-8");
}catch(Exception ex){}
String name=request.getParameter("name");
String subject=request.getParameter("subject");
String content=request.getParameter("content");
String pwd=request.getParameter("pwd");
BoardReplyVO vo=new BoardReplyVO();
vo.setName(name);
vo.setSubject(subject);
vo.setContent(content);
vo.setPwd(pwd);
BoardReplyDAO dao=BoardReplyDAO.newInstance();
dao.boardReplyInsert(vo);
return "redirect:../boardreply/list.do";
}
오라클에 값을 넘겨주는 메소드
VO로 잘 묶어서 메소드에 집어넣어준다. 그러면 글 내용이 오라클에 들어간다.
// detail
public BoardReplyVO boardReplyDetailData(int no)
{
BoardReplyVO vo=new BoardReplyVO();
try
{
getConnection();
String sql="UPDATE project_board_reply SET "
+"hit=hit+1 "
+"WHERE no=?";
ps=conn.prepareStatement(sql);
ps.setInt(1, no);
ps.executeUpdate();
sql="SELECT no,name,subject,content,regdate,hit "
+"FROM project_board_reply "
+"WHERE no=?";
ps=conn.prepareStatement(sql);
ps.setInt(1, no);
ResultSet rs=ps.executeQuery();
rs.next();
vo.setNo(rs.getInt(1));
vo.setName(rs.getString(2));
vo.setSubject(rs.getString(3));
vo.setContent(rs.getString(4));
vo.setRegdate(rs.getDate(5));
vo.setHit(rs.getInt(6));
rs.close();
}catch(Exception ex)
{
ex.printStackTrace();
}
finally
{
disConnection();
}
return vo;
}
디테일 출력
게시판에서 디테일을 가져올때는 항상 조회수 1을 먼저 증가시키고 내용을 불러오게 한다.
여기까지는 그냥 게시판과 거의 다를게 없다.
이제 다른 부분이 나온다. 글의 group_id를 받아와야 한다.
public int boardReplyGetGroupId(int no)
{
int gi=0;
try
{
getConnection();
String sql="SELECT group_id FROM project_board_reply "
+"WHERE no=?";
ps=conn.prepareStatement(sql);
ps.setInt(1, no);
ResultSet rs=ps.executeQuery();
rs.next();
gi=rs.getInt(1);
rs.close();
}catch(Exception ex)
{
}
finally
{
disConnection();
}
return gi;
}
글의 no를 받아와서 그룹아이디가 어떻게 되는지 확인해준다. 이걸 받아오는 이유는 관리자가 답변한 게시글이 어떤 아이디었는지 확인해주기 위해서이다.
public void boardReplyReplyInsert(BoardReplyVO vo)
{
try
{
getConnection();
String sql="INSERT INTO project_board_reply(no,name,subject,content,pwd, group_id, group_step, group_tab) "
+"VALUES((SELECT NVL(MAX(no)+1,1) FROM project_board_reply),?,?,?,?,"
+"?,1,1)";
ps=conn.prepareStatement(sql);
ps.setString(1, vo.getName());
ps.setString(2, vo.getSubject());
ps.setString(3, vo.getContent());
ps.setString(4, vo.getPwd());
ps.setInt(5, vo.getGroup_id());
ps.executeUpdate();
}catch(Exception ex)
{
ex.printStackTrace();
}
finally
{
disConnection();
}
}
답변하기 버튼을 누르고 답변을 입력하는 메소드
no는 자동증가, group_step과 group_tab은 각각 1로 고정해서 집어넣어준다. (group_id는 입력값으로 받아온다)
public boolean boardReplyCheck(int no)
{
boolean bCheck=false;
try
{
getConnection();
String sql="SELECT COUNT(group_id) FROM project_board_reply "
+"WHERE group_id=(SELECT group_id FROM project_board_reply WHERE no=?)";
ps=conn.prepareStatement(sql);
ps.setInt(1,no);
ResultSet rs=ps.executeQuery();
int count=rs.getInt(1);
if(count==2)
{
bCheck=true;
}
}
catch(Exception ex)
{
}
finally
{
disConnection();
}
return bCheck;
}
서브쿼리를 사용해서 답변이 달렸는지 아닌지 확인해주는 메소드
글번호를 받아와서 질문한 글의 group_id를 받아온다. 그리고 그 질문글과 같은 group_id인 글이 있는지 없는지 확인해준다.
count가 2면 답변이 이미 있다는 뜻이기 때문에 bCheck를 true로 바꿔주고 리턴한다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">
.mypage_row{
margin: 0px auto;
width:960px;
}
</style>
</head>
<body>
<div class="wrapper row3 mypage_row">
<h2 class="sectiontitle">묻고답하기</h2>
<div style="height: 500px;width:750px;overflow-y:auto;margin:0px auto">
<table class="table">
<tr>
<td>
<a href="../boardreply/insert.do" class="btn btn-sm btn-danger">등록</a>
</td>
</tr>
</table>
<table class="table">
<tr>
<th class="text-center" width=10%>번호</th>
<th class="text-center" width=45%>제목</th>
<th class="text-center" width=15%>이름</th>
<th class="text-center" width=20%>작성일</th>
<th class="text-center" width=10%>조회수</th>
</tr>
<c:forEach var="vo" items="${list }">
<tr>
<td class="text-center" width=10%>${vo.no }</td>
<td class="text-left" width=45%>
<c:if test="${vo.group_tab==1 }">
<img src="">
</c:if>
<a href="../boardreply/detail.do?no=${vo.no }">${vo.subject }</a>
</td>
<td class="text-center" width=15%>${vo.name }</td>
<td class="text-center" width=20%>${vo.regdate }</td>
<td class="text-center" width=10%>${vo.hit }</td>
</tr>
</c:forEach>
</table>
<table class="table">
<tr>
<td class="text-center">
<a href="#" class="btn btn-sm btn-success">이전</a>
${curpage } page / ${ totalpage} pages
<a href="#" class="btn btn-sm btn-info">다음</a>
</td>
</tr>
</table>
</div>
</div>
</body>
</html>
리스트에서 그룹탭이 1이면 공백을 2칸주고 출력한다.
@RequestMapping("boardreply/detail.do")
public String boardreply_detail(HttpServletRequest request,HttpServletResponse response)
{
String no=request.getParameter("no");
BoardReplyDAO dao=BoardReplyDAO.newInstance();
BoardReplyVO vo=dao.boardReplyDetailData(Integer.parseInt(no));
boolean bCheck=dao.boardReplyCheck(Integer.parseInt(no));
request.setAttribute("bCheck", bCheck);
request.setAttribute("vo", vo);
request.setAttribute("main_jsp", "../boardreply/detail.jsp");
return "../main/main.jsp";
}
detail은 답변이 있는지 없는지 boardReplyCheck로 true(답변이 있는지),false(답변이 없는지)를 bCheck로 받아온다.
답변하기 버튼을 누르면
@RequestMapping("boardreply/reply.do")
public String boardreply_reply(HttpServletRequest request,HttpServletResponse response)
{
String no=request.getParameter("no");
// db연동
BoardReplyDAO dao=BoardReplyDAO.newInstance();
int group_id=dao.boardReplyGetGroupId(Integer.parseInt(no));
request.setAttribute("group_id", group_id);
request.setAttribute("no", no);
request.setAttribute("main_jsp", "../boardreply/reply.jsp");
return "../main/main.jsp";
}
글번호를 받아오고, group_id 역시 셋팅해준다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">
.mypage_row{
margin: 0px auto;
width:960px;
}
</style>
</head>
<body>
<div class="wrapper row3 mypage_row">
<h2 class="sectiontitle">답변하기</h2>
<div style="height: 500px;width:750px;overflow-y:auto;margin:0px auto">
<%--
enctype="multipart/form-data" : 파일업로드시에 사용하는 프로토콜
--%>
<form method=post action="../boardreply/reply_ok.do">
<table class="table">
<tr>
<th width=20% class="text-right">이름</th>
<td width=80%>
<input type=text name=name size=15 class="input-sm" autocomplete="off" value="관리자" readonly>
</td>
</tr>
<tr>
<th width=20% class="text-right">제목</th>
<td width=80%>
<input type=text name=subject size=50 class="input-sm" autocomplete="off">
<input type=hidden name=no value="${no }">
<input type=hidden name=group_id value="${group_id }">
</td>
</tr>
<tr>
<th width=20% class="text-right">내용</th>
<td width=80%>
<textarea rows="10" cols="52" name=content autocomplete="off"></textarea>
</td>
</tr>
<tr>
<th width=20% class="text-right">비밀번호</th>
<td width=80%>
<input type=password name=pwd size=10 class="input-sm">
</td>
</tr>
<tr>
<td colspan="2" class="text-center">
<input type=submit value="답변" class="btn btn-sm btn-danger">
<input type=button value="취소" onclick="javascript:history.back()"
class="btn btn-sm btn-success"
>
</td>
</tr>
</table>
</form>
</div>
</div>
</body>
</html>
글번호(no)와 group_id는 hidden으로 넘겨준다.
@RequestMapping("boardreply/reply_ok.do")
public String boardreply_reply_ok(HttpServletRequest request,HttpServletResponse response)
{
try
{
request.setCharacterEncoding("UTF-8");
}catch(Exception ex){}
String name=request.getParameter("name");
String subject=request.getParameter("subject");
String content=request.getParameter("content");
String pwd=request.getParameter("pwd");
String group_id=request.getParameter("group_id");
BoardReplyVO vo=new BoardReplyVO();
vo.setName(name);
vo.setSubject(subject);
vo.setContent(content);
vo.setPwd(pwd);
vo.setGroup_id(Integer.parseInt(group_id));
BoardReplyDAO dao=BoardReplyDAO.newInstance();
dao.boardReplyReplyInsert(vo);
return "redirect:../boardreply/list.do";
}
값을 다 받아와서 저장해주고, list로 넘어가면 완성이다.
1번의 답변이 3번
사실 화살표 모양 아이콘을 줘야하는데 귀찮아서 안줬다.
'programming > Gukbi' 카테고리의 다른 글
국비 교육 75일차 - spring (Container, DI, DB연동) (0) | 2021.04.13 |
---|---|
국비 교육 74일차 - jsp 정리, spring 설치 (0) | 2021.04.12 |
국비 교육 71일차 - 파일 업로드 (0) | 2021.04.09 |
국비 교육 69일차 - 찜목록, 댓글 달기 수정 삭제 (0) | 2021.04.07 |
국비 교육 69일차 - 로그인 (0) | 2021.04.06 |