[JSP] 방명록 만들기(3)_삭제(delete)
Mission
3. 삭제
• Service ( 요청에 응답 메서드 구현 ) - DeleteMessageService.java
• Dao ( select 메서드, delete 메서드) -
• View - 40p
– form 구현 - confirmDeletion.jsp
– sevice delete 객체 생성, delete 메서드 호출
구체적인 설명
Message.java : DB와 연결을 편리하게 하기 위해, Getter/setter 메서드 설정.
MessageDao.java: 서비스 클래스에서 사용하기 위한 sql 구문 메서드들 정의.
DeleteMessageService.java: Delete를 하기 위한 메서드. Delete를 하기 위하여, MessageDao 클래스
에서 select(), delete()와 같은 메서드들을 불러 온다.
list.jsp : 요청을 받기 위한 뷰
confirmDeletion.jsp : 요청을 받기 위한 뷰
deleteMessage.jsp : 응답 결과를 반환하기 위한 뷰
<만드는 방법>
(1)list.jsp
<%@page import="guestbook.model.Message"%>
<%@page import="guestbook.model.MessageListView"%>
<%@page import="guestbook.service.GetMessageListService"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String pageNumberStr = request.getParameter("page");
int pageNumber = 1;
if (pageNumberStr != null) {
pageNumber = Integer.parseInt(pageNumberStr);
}
GetMessageListService messageListService = GetMessageListService.getInstance();
MessageListView viewData = messageListService.getMessageList(pageNumber);
%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>GuestBook</title>
<style>
</style>
</head>
<body>
<form action="writeMessage.jsp" method="post">
이름: <input type="text" name="guestName" /> <br /> 암호: <input
type="password" name="password" /> <br /> 메시지:
<textarea name="message" cols="30" row="3"></textarea>
<br /> <input type="submit" value="메시지 남기기" />
</form>
<hr>
<%
if (viewData.isEmpty()) {
%>
<h1>등록된 메시지가 없습니다.</h1>
<%
} else {
%>
<table border="1">
<%
for (Message message : viewData.getMessageList()) {
%>
<tr>
<td>메시지 번호: <%=message.getId()%><br />
손님 이름: <%=message.getGuestName()%><br />
메시지: <%=message.getMessage()%> <br />
<a href="confirmDeletion.jsp?messageId=<%=message.getId()%>">[삭제하기]</a>
</td>
</tr>
<%}%>
</table>
전체 페이지 카운트 <%= viewData.getPageTotalCount()%> <br>
<%for (int i = 1 ; i <= viewData.getPageTotalCount() ; i++) {%>
<a href="list.jsp?page=<%= i %>">[<%= i %>]</a>
<% }
}%>
</body>
</html>
(2)confirmDeletion.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<title>방명록 메시지 삭제 확인</title>
</head>
<body>
<form action="deleteMessage.jsp" method="post">
<input type="hidden" name="messageId" value=" ${param.messageId}*" />
메시지를 삭제하시려면 암호를 입력하세요:<br />
암호: <input type="password" name="password" /> <br />
<input type="submit" value="메시지 삭제하기" />
</form>
</body>
</html>
*getParameter로 list.jsp에서 messageId를 가져온다.
(3)DeleteMessageService/DeleteMessageService.java
package DeleteMessageService;
import java.sql.Connection;
import java.sql.SQLException;
import guestbook.dao.MessageDao;
import guestbook.model.Message;
import guestbook.service.ServiceException;
import jdbc.JdbcUtil;
import jdbc.connection.ConnectionProvider;
public class DeleteMessageService {
// 싱글톤 생성: 다른 곳에서 객체 생성 불필요하도록
private static DeleteMessageService instance = new DeleteMessageService();
public static DeleteMessageService getInstance() {
return instance;
}
private DeleteMessageService() {
}
//deleteMessage()
public void deleteMessage(int messageId, String password)
throws ServiceException, InvalidMessagePassowrdException, MessageNotFoundException {
// 방명록 만들기(2)에서 만들어준 guestbook.service/ServiceException.java를 import 한다.
// InvalidMessagePassowrdException.java, MessageNotFoundException.java 클래스를 새로
// 만들어준다. 자동완성으로 하면 편리함.
Connection conn = null;
try {
conn = ConnectionProvider.getConnection();
conn.setAutoCommit(false);
MessageDao dao = MessageDao.getInstance();
// MessageDao에서 메서드를 사용가능하게 하도록 MessageDao의 싱글톤을 불러온다.
Message message = dao.select(conn, messageId);
// MessageDao.java 클래스에 Message타입의 select(conn, messageId)를 만들어주러 간다.
// 만들고 돌아왔다.
// 게시물 유무 확인 : 없다면 예외 발생
if (message == null) {
throw new MessageNotFoundException("메시지가 없습니다:" + messageId);
}
// 비밀 번호 존재 유무 확인 : 없다면 예외 발생
if (!message.hasPassword()) {
throw new InvalidMessagePassowrdException();
}
// 비밀번호 비교 : 틀리면 예외 발생
if (!message.getPassword().equals(password)) {
throw new InvalidMessagePassowrdException();
}
// 삭제 처리_ MessageDao.java 클래스로 가서 delete() 메서드를 만들어 준다.
dao.delete(conn, messageId);
// 트랜잭션 완료 : commit
conn.commit();
} catch (SQLException e) {
JdbcUtil.rollback(conn);
} catch (InvalidMessagePassowrdException e) {
JdbcUtil.rollback(conn);
throw e;
} catch (MessageNotFoundException e) {
JdbcUtil.rollback(conn);
throw e;
} finally {
if (conn != null) {
try {
conn.setAutoCommit(false);
} catch (SQLException e) {
}
JdbcUtil.close(conn);
}
}
}
}
예외처리 클래스들은 예외를 사용하고자 하는 클래스(ex.DeleteMessageService.java
)에 미리 적어두면 빨간 줄이 뜬다. 그때 자동완성을 사용하여 ‘Create ---Exception.class’ 등의
문구를 클릭하면 편리하다.
[MessageNotFoundException.java]
package DeleteMessageService;
public class InvalidMessagePassowrdException extends Exception {
}
[InvalidMessagePassowrdException.java]
package DeleteMessageService;
public class MessageNotFoundException extends Exception {
public MessageNotFoundException(String arg0) {
super(arg0);
// TODO Auto-generated constructor stub
}
}
(4)MessageDao.java
package guestbook.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import guestbook.model.Message;
import jdbc.JdbcUtil;
public class MessageDao {
// DAO 클래스는 기능 클래스 --> 여러 개의 인스턴스 생성이 불필요하다.
// 결론 --> 싱글톤 패턴으로 처리 하자.
// 1.private 생성자
private MessageDao() {
}
// 2.인스턴스 생성 : 1개 생성하고 공유해서 사용.
private static MessageDao instance = new MessageDao();
// 3. 외부에서 사용할 수 있는 메서드 생성.
public static MessageDao getInstance() {
return instance;
}
// Insert_insert() 메서드
public int insert(Connection conn, Message message) throws SQLException {
PreparedStatement pstmt = null;
String sql = "insert into guestbook_message values (message_id_seq.NEXTVAL, ?, ?, ?)";
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, message.getGuestName());
pstmt.setString(2, message.getPassword());
pstmt.setString(3, message.getMessage());
return pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtil.close(pstmt);
}
return 0;
}
// Select_ selectCount() 메세지_for 전체 게시물 수(messageTotalCount)
public int selectCount(Connection conn) throws SQLException {
Statement stmt = null;
ResultSet rs = null;
String sql = "select count(*) from guestbook_message";
try {
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
rs.next();
return rs.getInt(1);
} finally {
JdbcUtil.close(rs);
JdbcUtil.close(stmt);
}
}
//Select_ selectList()
public List<Message> selectList(Connection conn, int firstRow, int endRow) throws SQLException {
PreparedStatement pstmt = null;
ResultSet rs = null;
List<Message> messageList = null;
String sql = "select message_id, guest_name, password, message " + "from ( "
+ "select rownum rnum, message_id, guest_name, password, message " + "from ( " + "select * "
+ "from guestbook_message m " + "order by m.message_id desc " + ") " + "where rownum <= ? " + ") "
+ "where rnum >= ? " + "";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, endRow);
pstmt.setInt(2, firstRow);
rs = pstmt.executeQuery();
if (rs.next()) {
messageList = new ArrayList<Message>();
do {
messageList.add(makeMessageFromResultSet(rs));
} while (rs.next());
} else {
messageList = Collections.emptyList();
}
return messageList;
}
// ResultSet rs의 결과가 있다면 읽어오는 메서드.
private Message makeMessageFromResultSet(ResultSet rs) throws SQLException {
Message message = new Message();
message.setId(rs.getInt("message_id"));
message.setGuestName(rs.getString("guest_name"));
message.setPassword(rs.getString("password"));
message.setMessage(rs.getString("message"));
return message;
}
//Delete_delete 하기 위하여 읽어 오는 메서드.
public Message select(Connection conn, int messageId) throws SQLException {
PreparedStatement pstmt = null;
ResultSet rs = null;
Message message = null;
String sql = "select * from guestbook_message where message_id=?";
try {
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, messageId);
rs = pstmt.executeQuery();
if (rs.next()) {
message = makeMessageFromResultSet(rs);
// message가 있다면 makeMessageFromResultSet(ResultSet rs) 메서드를 이용하여 결과 읽어온다.
}
} finally {
JdbcUtil.close(rs);
JdbcUtil.close(pstmt);
}
return message;
}
//Delete_delete 하는 메서드
public int delete(Connection conn, int messageId) throws SQLException {
PreparedStatement pstmt = null;
String sql = "delete from guestbook_message where message_id = ?";
try {
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, messageId);
pstmt.executeUpdate();
}finally {
JdbcUtil.close(pstmt);
}
return messageId;
}
}
(5) deleteMessage.jsp 결과를 반환해주는 뷰 역할
<%@page import="DeleteMessageService.InvalidMessagePassowrdException"%>
<%@page import="DeleteMessageService.DeleteMessageService"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
//1. 사용자의 요청 정보 가져오기
int messageId = Integer.parseInt(request.getParameter("messageId"));
String password = request.getParameter("password");
boolean invalidPassowrd = false;
try {
//2. 요청 처리를 위한 서비스 객체 생성
DeleteMessageService deleteService = DeleteMessageService.getInstance();
//3. 삭제 요청_ 메서드를 실행한다.
deleteService.deleteMessage(messageId, password);
} catch (InvalidMessagePassowrdException ex) {
invalidPassowrd = true;
}
%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<style>
</style>
</head>
<body>
<%
if (!invalidPassowrd) {
%>
메시지를 삭제하였습니다.
<%
} else {
%>
입력한 암호가 올바르지 않습니다. 암호를 확인해주세요.
<%
}
%>
<br />
<a href="list.jsp">[목록 보기]</a>
</body>
</html>
방명록 삭제를 해보았다. 여기서 가장 실수가 빈번히 일어나는 것은 데이터 타입 설정이니, 주의하시길 바란다. 마치 나처럼 실수할 가능성이 다분하기 때문에.
댓글 없음:
댓글 쓰기