모델 1 게시판
모델 1이란 JSP안의 자바 코드를 떼어 내 자바 빈즈로 만든 코드를 말한다. 이전 절의 게시판 코드는 JSP안에 JDBC 코드가 포함되어 있다. 이런 코드는 악몽이라 불리는 코드로, 최소한 JDBC 관련 코드는 자바 빈즈에 있어야 한다. 모델 1 게시판으로 수정하기 위해 먼저 게시글 정보를 담기 위한 자바 빈즈를 다음과 같이 생성한다.
Article.java
package net.java_school.board; import java.util.Date; public class Article { public static final String LINE_SEPARATOR = System.getProperty("line.separator"); private int no; private String title; private String content; private Date wdate; private int parent; private int indent; public int getNo() { return no; } public void setNo(int no) { this.no = no; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { if (content == null) content = ""; return content; } public void setContent(String content) { this.content = content; } public String getHtmlContent() { if (content == null) { return ""; } else { return content.replaceAll(LINE_SEPARATOR, "<br />"); } } public Date getWdate() { return wdate; } public void setWdate(Date wdate) { this.wdate = wdate; } public int getParent() { return parent; } public void setParent(int parent) { this.parent = parent; } public int getIndent() { return indent; } public void setIndent(int indent) { this.indent = indent; } }
Article.java의 필드는 board 테이블의 컬럼과 매핑된다. board 테이블에서 indent 컬럼이 없다. indent 필드는 목록(list.jsp)에서 목록 아이템을 들여쓰기할 때 필요하다.
getHtmlContent() 메소드는 content 컬럼에 저장되어 있는 개행문자를 <br />로 바꾸는 메소드이다. 이 메소드는 상세보기(view.jsp)에서 사용된다.
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
LINE_SEPARATOR 상수는 getHtmlContent() 메소드에서 사용한다.
여기서 자바 프로그램에서 상수를 관리하는 팁을 소개한다.
WebContants.java
package net.java_school.commons; public class WebContants { //Line Separator public final static String LINE_SEPARATOR = System.getProperty("line.separator"); }
이렇게 수정하면 Article에서 LINE_SEPARATOR 선언을 제거해야 하고 Article의 getHtmlContent() 메소드는 다음과 같이 수정해야 한다.
//.. 중간 생략 .. import net.java_school.commons.WebContants; public class Article { //public static final String LINE_SEPARATOR = System.getProperty("line.separator"); 제거한다. //.. 중간 생략 .. public String getHtmlContent() { if (content == null) { return ""; } else { return content.replaceAll(WebContants.LINE_SEPARATOR, "<br />"); } } //.. 중간 생략 .. }
WebContants 클래스를 enum으로 바꿀 수 있다.
WebContants.java
package net.java_school.commons; public enum WebContants { lineSeparator (System.getProperty("line.separator")); public String value; WebContants (String value) { this.value = value; } }
enum으로 바꾸면 Article 클래스는 다음과 같이 바뀐다.
//.. 중간 생략 .. import net.java_school.commons.WebContants; public class Article { //.. 중간 생략 .. public String getHtmlContent() { if (content == null) { return ""; } else { return content.replaceAll(WebContants.lineSeparator.value, "<br />"); } } //.. 중간 생략 .. }
다음으로 JDBC를 담당하는 BoardDao 빈즈를 작성한다. 이름 뒤에 Dao는 Data Access Object의 약자이다. 이와 같은 이름을 가진 빈은 JDBC 관련 코드만을 지녀야 한다. 이를 DAO 패턴이라 한다.
BoardDao.java
package net.java_school.board; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import java.util.ArrayList; import net.java_school.db.dbpool.OracleConnectionManager; import net.java_school.util.Log; public class BoardDao { private OracleConnectionManager dbmgr; public BoardDao() {} public BoardDao() { this.dbmgr = dbmgr; } private Connection getConnection() throws SQLException { return dbmgr.getConnection(); } private void close(ResultSet rs, PreparedStatement stmt, Connection con) { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (con != null) { dbmgr.freeConnection(con); } } public List<Article> getBoardList(int start, int end, String keyword) { Log log = new Log(); List<Article> list = new ArrayList<Article>(); String sql = null; sql = "SELECT no, indent, parent, title, wdate FROM " + "(SELECT ROWNUM R, A.* " + "FROM " + "(SELECT no, level as indent, parent, title, wdate FROM board "; if (keyword != null && !keyword.equals("")) { sql += " WHERE title LIKE '%" + keyword + "%' OR content LIKE '%" + keyword + "%' "; } sql += "START WITH parent = 0 " + "CONNECT BY PRIOR no = parent " + "ORDER SIBLINGS BY no DESC) A) " + "WHERE R BETWEEN ? AND ?"; Connection con = null; PreparedStatement stmt = null; ResultSet rs = null; try { con = getConnection(); stmt = con.prepareStatement(sql); if (keyword == null || keyword.equals("")) { stmt.setInt(1, start); stmt.setInt(2, end); } else { stmt.setString(1, keyword); stmt.setString(2, keyword); stmt.setInt(3, start); stmt.setInt(4, end); } rs = stmt.executeQuery(); while (rs.next()) { Article article = new Article(); article.setNo(rs.getInt("no")); article.setTitle(rs.getString("title")); article.setWdate(rs.getDate("wdate")); article.setIndent(rs.getInt("indent")); list.add(article); } } catch (SQLException e) { log.debug("Error Source : BoardDao.getBoardList() : SQLException"); log.debug("SQLState : " + e.getSQLState()); log.debug("Message : " + e.getMessage()); log.debug("Oracle Error Code : " + e.getErrorCode()); log.debug("sql : " + sql); } finally { close(rs, stmt, con); log.close(); } return list; } public int getTotalRecord(String keyword) { Log log = new Log(); int totalRecord = 0; String sql = null; sql = "SELECT count(*) FROM board "; if (keyword != null && !keyword.equals("")) { sql += "WHERE title LIKE ? OR content LIKE ?"; } Connection con = null; PreparedStatement stmt = null; ResultSet rs = null; try { con = getConnection(); stmt = con.prepareStatement(sql); if (keyword != null && !keyword.equals("")) { keyword = "%" + keyword + "%"; stmt.setString(1, keyword); stmt.setString(2, keyword); } rs = stmt.executeQuery(); rs.next(); totalRecord = rs.getInt(1); } catch (SQLException e) { log.debug("Error Source : BoardDao.getTotalRecord() : SQLException"); log.debug("SQLState : " + e.getSQLState()); log.debug("Message : " + e.getMessage()); log.debug("Oracle Error Code : " + e.getErrorCode()); log.debug("sql : " + sql); } finally { close(rs, stmt, con); log.close(); } return totalRecord; } }
다음 메소드는 목록의 페이지 매기기에 필요한 숫자를 만들어낸다.
public Map<String, Integer> getNumbersForPaging(int totalRecord, int curPage, int numPerPage, int pagePerBlock) { Map<String, Integer> map = new HashMap<String, Integer>(); int totalPage = totalRecord / numPerPage; if (totalRecord % numPerPage != 0) totalPage++; int totalBlock = totalPage / pagePerBlock; if (totalPage % pagePerBlock != 0) totalBlock++; int block = curPage / pagePerBlock; if (curPage % pagePerBlock != 0) block++; int firstPage = (block - 1) * pagePerBlock + 1; int lastPage = block * pagePerBlock; int prevPage = 0; if (block > 1) { prevPage = firstPage - 1; } int nextPage = 0; if (block < totalBlock) { nextPage = lastPage + 1; } if (block >= totalBlock) { lastPage = totalPage; } int listItemNo = totalRecord - (curPage - 1) * numPerPage; map.put("totalPage", totalPage); map.put("firstPage", firstPage); map.put("lastPage", lastPage); map.put("prevPage", prevPage); map.put("nextPage", nextPage); map.put("listItemNo", listItemNo); return map; }
/board/list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="net.java_school.board.*" %> <%@ page import="java.util.*" %> <%! public Map<String, Integer> getNumbersForPaging(int totalRecord, int curPage, int numPerPage, int pagePerBlock) { Map<String, Integer> map = new HashMap<String, Integer>(); int totalPage = totalRecord / numPerPage; if (totalRecord % numPerPage != 0) totalPage++; int totalBlock = totalPage / pagePerBlock; if (totalPage % pagePerBlock != 0) totalBlock++; int block = curPage / pagePerBlock; if (curPage % pagePerBlock != 0) block++; int firstPage = (block - 1) * pagePerBlock + 1; int lastPage = block * pagePerBlock; int prevPage = 0; if (block > 1) { prevPage = firstPage - 1; } int nextPage = 0; if (block < totalBlock) { nextPage = lastPage + 1; } if (block >= totalBlock) { lastPage = totalPage; } int listItemNo = totalRecord - (curPage - 1) * numPerPage; map.put("totalPage", totalPage); map.put("firstPage", firstPage); map.put("lastPage", lastPage); map.put("prevPage", prevPage); map.put("nextPage", nextPage); map.put("listItemNo", listItemNo); return map; } %> <% request.setCharacterEncoding("UTF-8"); int curPage = request.getParameter("curPage") == null ? 1 : Integer.parseInt(request.getParameter("curPage")); String keyword = request.getParameter("keyword"); if (keyword == null) keyword = ""; BoardDao dao = new BoardDao(); int totalRecord = dao.getTotalRecord(keyword); int numPerPage = 10; int pagePerBlock = 5; Map<String, Integer> numbers = this.getNumbersForPaging(totalRecord, curPage, numPerPage, pagePerBlcok); int startRecord = (curPage - 1) * numPerPage + 1; int endRecord = curPage * numPerPage; List<Article> list = dao.getBoardList(startRecord, endRecord, keyword); %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>목록</title> </head> <body style="font-size: 11px;"> <h1>목록</h1> <% int listItemNo = numbers.get("listItemNo");//이 값은 목록 페이지에서 계산되는 번호다. no 컬럼 값이 아니다. for (int i = 0; i < list.size(); i++) { Article article = list.get(i); int indent = article.getIndent(); for (int j = 0; j < indent; j++) { out.println(" "); } if(indent != 1) { out.println("⌙"); } %> <%=listItemNo %> <a href="view.jsp?no=<%=article.getNo() %>&curPage=<%=curPage %>&keyword=<%=keyword %>"><%=article.getTitle() %></a> <%=article.getWdate() %><br /> <hr /> <% listItemNo--; } int prevPage = numbers.get("prevPage"); if (prevPage != 0) { %> <a href="list.jsp?curPage=<%=prevPage %>&keyword=<%=keyword %>">[이전]</a> <% } int firstPage = numbers.get("firstPage"); int lastPage = numbers.get("lastPage"); for (int i = firstPage; i <= lastPage; i++) { %> <a href="list.jsp?curPage=<%=i %>&keyword=<%=keyword %>">[<%=i %>]</a> <% } int nextPage = numbers.get("nextPage"); if (nextPage != 0) { %> <a href="list.jsp?curPage=<%=nextPage %>&keyword=<%=keyword %>">[다음]</a> <% } %> <p> <a href="write_form.jsp?curPage=<%=curPage %>&keyword=<%=keyword %>">글쓰기</a> </p> <form method="get"> <input type="text" size="10" maxlength="30" name="keyword" /> <input type="submit" value="Search" /> </form> </body> </html>
목록을 방문하여 테스트한다. 간단한 게시판은 Article과 BoardDao 정도로 충분하지만, 대부분 모듈은 JSP의 프런트 역할을 하는 빈즈을 따로 두는 경우가 많다. 이 빈즈의 이름에는 Service란 이름이 붙는다. 게시판 JSP의 프런트 역할을 하는 BoardService 빈즈를 생성한다. BoardService를 만들면 게시판 JSP는 BoardService만을 바라보게 된다. 위 list.jsp에 선언된 getNumbersForPaging() 메소드는 BoardService로 옮길 수 있다.
BoardService.java
package net.java_school.board; import java.util.Map; import java.util.HashMap; import java.util.List; public class BoardService { private BoardDao dao = new BoardDao(); public BoardService() {} public Map<String, Integer> getNumbersForPaging(int totalRecord, int curPage, int numPerPage, int pagePerBlock) { Map<String, Integer> map = new HashMap<String, Integer>(); int totalPage = totalRecord / numPerPage; if (totalRecord % numPerPage != 0) totalPage++; int totalBlock = totalPage / pagePerBlock; if (totalPage % pagePerBlock != 0) totalBlock++; int block = curPage / pagePerBlock; if (curPage % pagePerBlock != 0) block++; int firstPage = (block - 1) * pagePerBlock + 1; int lastPage = block * pagePerBlock; int prevPage = 0; if (block > 1) { prevPage = firstPage - 1; } int nextPage = 0; if (block < totalBlock) { nextPage = lastPage + 1; } if (block >= totalBlock) { lastPage = totalPage; } int listItemNo = totalRecord - (curPage - 1) * numPerPage; map.put("totalPage", totalPage); map.put("firstPage", firstPage); map.put("lastPage", lastPage); map.put("prevPage", prevPage); map.put("nextPage", nextPage); map.put("listItemNo", listItemNo); return map; } public List<Article> getBoardList(int startRecord, int endRecord, String keyword) { return dao.getBoardList(startRecord, endRecord, keyword); } public int getTotalRecord(String keyword) { return dao.getTotalRecord(keyword); } }
BoardService.java만을 사용하도록 list.jsp를 수정한다.
/board/list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="net.java_school.board.*" %> <%@ page import="net.java_school.commons.*" %> <%@ page import="java.util.*" %> <% int curPage = (request.getParameter("curPage") == null ? 1 : Integer.parseInt(request.getParameter("curPage"))); String keyword = request.getParameter("keyword"); if (keyword == null) keyword = ""; BoardService service = new BoardService(); int totalRecord = service.getTotalRecord(keyword); int numPerPage = 10; int pagePerBlock = 5; Map<String, Integer> numbers = service.getNumbersForPaging(totalRecord, curPage, numPerPage, pagePerBlock); int startRecord = (curPage - 1) * numPerPage + 1; int endRecord = curPage * numPerPage; List<Article> list = service.getBoardList(startRecord, endRecord, keyword); %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>목록</title> </head> <body style="font-size: 11px;"> <h1>목록</h1> <% int listItemNo = numbers.get("listItemNo"); for (int i = 0; i < list.size(); i++) { Article article = list.get(i); int indent = article.getIndent(); for (int j = 0; j < indent; j++) { out.println(" "); } if(indent != 1) { out.println("⌙"); } %> <%=listItemNo %> <a href="view.jsp?no=<%=article.getNo() %>&curPage=<%=curPage %>&keyword=<%=keyword %>"><%=article.getTitle() %></a> <%=article.getWdate() %><br /> <hr /> <% listItemNo--; } int prevPage = numbers.get("prevPage"); if (prevPage != 0) { %> <a href="list.jsp?curPage=<%=prevPage %>&keyword=<%=keyword %>">[이전]</a> <% } int firstPage = numbers.get("firstPage"); int lastPage = numbers.get("lastPage"); for (int i = firstPage; i <= lastPage; i++) { %> <a href="list.jsp?curPage=<%=i %>&keyword=<%=keyword %>">[<%=i %>]</a> <% } int nextPage = numbers.get("nextPage"); if (nextPage != 0) { %> <a href="list.jsp?curPage=<%=nextPage %>&keyword=<%=keyword %>">[다음]</a> <% } %> <p> <a href="write_form.jsp?curPage=<%=curPage %>&keyword=<%=keyword %>">글쓰기</a> </p> <form method="get"> <input type="text" size="10" maxlength="30" name="keyword" /> <input type="submit" value="Search" /> </form> </body> </html>
/board/write_form.jsp 파일의 폼 태그의 action 속성값을 write.jsp로 수정한다.
/board/write_form.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String curPage = request.getParameter("curPage"); String keyword = request.getParameter("keyword"); %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>글쓰기</title> </head> <body> <h3>새 글쓰기</h3> <form action="write.jsp" method="post"> <table> <tr> <td>제목</td> <td><input type="text" name="title" size="50"></td> </tr> <tr> <td colspan="2"> <textarea name="content" rows="20" cols="100"></textarea> </td> </tr> <tr> <td colspan="2"> <input type="submit" value="전송"> <input type="reset" value="취소"> <a href="list.jsp?curPage=<%=curPage %>&keyword=<%=keyword %>">목록</a> </td> </tr> </table> </form> </body> </html>
BoardDao 클래스에 다음 메소드를 추가한다.
BoardDao.java
public void insert(Article article) { Log log = new Log(); String sql = "INSERT INTO board (no, title, content, wdate, parent) " + "VALUES (board_no_seq.nextval, ?, ?, sysdate, 0)"; Connection con = null; PreparedStatement stmt = null; try { con = getConnection(); stmt = con.prepareStatement(sql); stmt.setString(1, article.getTitle()); stmt.setString(2, article.getContent()); stmt.executeUpdate(); } catch (SQLException e) { log.debug("Error Source : BoardDao.insert() : SQLException"); log.debug("SQLState : " + e.getSQLState()); log.debug("Message : " + e.getMessage()); log.debug("Oracle Error Code : " + e.getErrorCode()); log.debug("sql : " + sql); } finally { close(null, stmt, con); log.close(); } }
BoardService에 다음 메소드를 추가한다.
BoardService.java 수정
public void write(Article article) { dao.insert(article); }
새 글쓰기를 처리하는 write.jsp 파일을 만든다.
/board/write.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="net.java_school.board.*" %> <% request.setCharacterEncoding("UTF-8"); String title = request.getParameter("title"); String content = request.getParameter("content"); Article article = new Article(); article.setTitle(title); article.setContent(content); BoardService service= new BoardService(); service.write(article); response.sendRedirect("list.jsp"); %>
다음으로 상세보기 구현한다. BoardDao에 selectOne() 메소드를 추가한다.
BoardDao.java
public Article selectOne(int no) { Log log = new Log(); Article article = null; String sql = "SELECT no, title, content, wdate FROM board WHERE no = ?"; Connection con = null; PreparedStatement stmt = null; ResultSet rs = null; try { con = getConnection(); stmt = con.prepareStatement(sql); stmt.setInt(1, no); rs = stmt.executeQuery(); while (rs.next()) { article = new Article(); article.setNo(rs.getInt("no")); article.setTitle(rs.getString("title")); article.setContent(rs.getString("content")); article.setWdate(rs.getDate("wdate")); } } catch (SQLException e) { log.debug("Error Source : BoardDao.selectOne() : SQLException"); log.debug("SQLState : " + e.getSQLState()); log.debug("Message : " + e.getMessage()); log.debug("Oracle Error Code : " + e.getErrorCode()); log.debug("sql : " + sql); } finally { close(rs, stmt, con); log.close(); } return article; }
BoardService에 다음 메소드를 추가한다.
BoardService.java
public Article getArticle(int no) { return dao.selectOne(no); }
view.jsp를 아래와 같이 수정한다.
/board/view.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="net.java_school.board.*" %> <% int no = Integer.parseInt(request.getParameter("no")); String curPage = request.getParameter("curPage"); String keyword = request.getParameter("keyword"); if (keyword == null) keyword = ""; BoardService service = new BoardService(); Article article = service.getArticle(no); %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>상세보기</title> <script type="text/javascript"> function goModify(no,curPage,keyword) { location.href="modify_form.jsp?no=" + no + "&curPage=" + curPage + "&keyword=" + keyword; } function goDelete(no,curPage,keyword) { var check = confirm("정말로 삭제하겠습니까?"); if (check) { location.href="del.jsp?no=" + no + "&curPage=" + curPage + "&keyword=" + keyword; } } </script> </head> <body> <h1>상세보기</h1> <h2>제목: <%=article.getTitle() %>, 작성일: <%=article.getWdate() %></h2> <p> <%=article.getHtmlContent() %> </p> <a href="list.jsp?curPage=<%=curPage %>&keyword=<%=keyword %>">목록</a> <input type="button" value="수정" onclick="javascript:goModify('<%=no %>','<%=curPage %>','<%=keyword %>')"> <input type="button" value="삭제" onclick="javascript:goDelete('<%=no %>','<%=curPage %>','<%=keyword %>')"> <a href="reply_form.jsp?no=<%=no %>&curPage=<%=curPage %>&keyword=<%=keyword %>">답변쓰기</a> </body> </html>
다음으로 글 수정을 구현한다. BoardDao 클래스에 update() 메소드를 추가한다.
BoardDao.java
public void update(Article article) { Log log = new Log(); String sql = "UPDATE board SET title = ?, content = ? WHERE no = ?"; Connection con = null; PreparedStatement stmt = null; try { con = getConnection(); stmt = con.prepareStatement(sql); stmt.setString(1, article.getTitle()); stmt.setString(2, article.getContent()); stmt.setInt(3, article.getNo()); stmt.executeUpdate(); } catch (SQLException e) { log.debug("Error Source : BoardDao.update() : SQLException"); log.debug("SQLState : " + e.getSQLState()); log.debug("Message : " + e.getMessage()); log.debug("Oracle Error Code : " + e.getErrorCode()); log.debug("sql : " + sql); } finally { close(null, stmt, con); log.close(); } }
BoardService.java 수정
public void modify(Article article) { dao.update(article); }
modify_form.jsp가 BoardService를 사용하도록 수정한다.
/board/modify_form.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.sql.*" %> <%@ page import="net.java_school.board.*" %> <% int no = Integer.parseInt(request.getParameter("no")); String curPage = request.getParameter("curPage"); String keyword = request.getParameter("keyword"); BoardService service = new BoardService(); Article article = service.getArticle(no); %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>수정</title> </head> <body> <h1>수정</h1> <form action="modify.jsp" method="post"> <input type="hidden" name="no" value="<%=no %>"> <input type="hidden" name="curPage" value="<%=curPage %>"> <input type="hidden" name="keyword" value="<%=keyword %>"> <table> <tr> <td>제목</td> <td><input type="text" name="title" size="50" value="<%=article.getTitle() %>" /></td> </tr> <tr> <td colspan="2"> <textarea name="content" rows="30" cols="100"><%=article.getContent() %></textarea> </td> </tr> <tr> <td colspan="2"> <input type="submit" value="전송"> <input type="reset" value="취소"> <a href="view.jsp?no=<%=no %>&curPage=<%=curPage %>&keyword=<%=keyword %>">상세보기</a> </td> </tr> </table> </form> </body> </html>
modify.jsp를 아래와 같이 생성한다.
/board/modify.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="net.java_school.board.*" %> <% request.setCharacterEncoding("UTF-8"); int no = Integer.parseInt(request.getParameter("no")); String curPage = request.getParameter("curPage"); String keyword = request.getParameter("keyword"); String title = request.getParameter("title"); String content = request.getParameter("content"); Article article = new Article(); article.setNo(no); article.setTitle(title); article.setContent(content); BoardService service= new BoardService(); service.modify(article); keyword = java.net.URLEncoder.encode(keyword,"UTF-8"); response.sendRedirect("view.jsp?no=" + no + "&curPage=" + curPage + "&keyword=" + keyword); %>
다음으로 글 삭제를 구현한다. BoardDao 클래스에 delete() 메소드를 추가한다.
BoardDao.java
public void delete(int no) { Log log = new Log(); String sql1 = "SELECT count(*) FROM board WHERE parent = ?"; String sql2 = "DELETE FROM board WHERE no = ?"; Connection con = null; PreparedStatement stmt1 = null; PreparedStatement stmt2 = null; ResultSet rs = null; boolean check = false; //true면 삭제 try { con = getConnection(); stmt1 = con.prepareStatement(sql1); stmt1.setInt(1, no); rs = stmt1.executeQuery(); rs.next(); int num = rs.getInt(1); if (num == 0) { check = true; } if (check == true) { stmt2 = con.prepareStatement(sql2); stmt2.setInt(1, no); stmt2.executeUpdate(); } } catch (SQLException e) { log.debug("Error Source : BoardDao.delete() : SQLException"); log.debug("SQLState : " + e.getSQLState()); log.debug("Message : " + e.getMessage()); log.debug("Oracle Error Code : " + e.getErrorCode()); log.debug("sql : " + sql1); } finally { if (stmt1 != null) { try { stmt1.close(); } catch (SQLException e) {} } close(rs, stmt2, con); log.close(); } }
BoardService에 다음 메소드를 추가한다.
BoardService.java
public void delete(int no) { dao.delete(no); }
del.jsp를 다음과 같이 생성한다.
/board/del.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="net.java_school.board.*" %> <% int no = Integer.parseInt(request.getParameter("no")); String curPage = request.getParameter("curPage"); String keyword = request.getParameter("keyword"); BoardService service= new BoardService(); service.delete(no); keyword = java.net.URLEncoder.encode(keyword,"UTF-8"); response.sendRedirect("list.jsp?curPage=" + curPage + "&keyword=" + keyword); %>
답변글이 있으면 삭제되지 않는다. 다음으로 답변쓰기를 구현한다. BoardDao에 다음 메소드를 추가한다.
BoardDao.java
public void reply(Article article) { Log log = new Log(); //답변쓰기용 쿼리 String sql = "INSERT INTO board " + "(no, parent, title, content, wdate) " + "VALUES (board_no_seq.nextval, ?, ?, ?, sysdate)"; Connection con = null; PreparedStatement stmt = null; try { con = getConnection(); stmt = con.prepareStatement(sql); stmt.setInt(1, article.getParent()); stmt.setString(2, article.getTitle()); stmt.setString(3, article.getContent()); stmt.executeUpdate(); } catch (SQLException e) { log.debug("Error Source:BoardDao.reply() : SQLException"); log.debug("SQLState : " + e.getSQLState()); log.debug("Message : " + e.getMessage()); log.debug("Oracle Error Code : " + e.getErrorCode()); log.debug("sql : " + sql); } finally { close(null, stmt, con); log.close(); } }
BoardService에 reply() 메소드를 추가한다.
BoardService.java
public void reply(Article article) { dao.reply(article); }
/board/reply_form.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="net.java_school.board.*" %> <%@ page import="net.java_school.commons.*" %> <% int no = Integer.parseInt(request.getParameter("no")); String curPage = request.getParameter("curPage"); String keyword = request.getParameter("keyword"); BoardService service = new BoardService(); Article article = service.getArticle(no); String content = article.getContent(); //부모글을 구별하기 위해 부모글의 각 행마다 >가 추가되도록 한다. content = content.replaceAll(WebContants.lineSeparator.value, WebContants.lineSeparator.value + ">"); content = WebContants.lineSeparator.value + WebContants.lineSeparator.value + ">" + content; %> <html> <head> <meta charset="UTF-8" /> <title>답변쓰기</title> </head> <body> <h1>답변쓰기</h1> <form action="reply.jsp" method="post"> <input type="hidden" name="no" value="<%=no %>" /> <input type="hidden" name="curPage" value="<%=curPage %>" /> <input type="hidden" name="keyword" value="<%=keyword %>" /> 제목 : <input type="text" name="title" size="45" value="<%=article.getTitle() %>" /><br /> <textarea name="content" rows="10" cols="60"><%=content %></textarea><br /> <input type="submit" value="전송" /> <input type="reset" value="취소" /><br /> </form> <a href="view.jsp?no=<%=no %>&curPage=<%=curPage %>&keyword=<%=keyword %>">상세보기</a> </body> </html>
reply.jsp를 아래와 같이 생성한다.
/board/reply.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="net.java_school.board.*" %> <% request.setCharacterEncoding("UTF-8"); int parent = Integer.parseInt(request.getParameter("no")); String title = request.getParameter("title"); String content = request.getParameter("content"); String curPage = request.getParameter("curPage"); String keyword = request.getParameter("keyword"); Article article = new Article(); article.setParent(parent); article.setTitle(title); article.setContent(content); BoardService service= new BoardService(); service.reply(article); keyword = java.net.URLEncoder.encode(keyword,"UTF-8"); response.sendRedirect("list.jsp?curPage=" + curPage + "&keyword=" + keyword); %>