JSP 18강 - DBCP 이용한 방명록 게시판(CRUD)

voilà!·2022년 2월 2일
0

JSP 스프링

목록 보기
18/31

실행 순서
JSP -> service -> dao -> db
JSP <- service <- dao <- db

jquery 다운로드
https://jquery.com/ 접속
download 클릭
upcompressed 클릭 -> 내용 복사
js폴더에 파일 만들고, 복사한 내용 붙여넣기
---> 이제 script src에 해당 위치 적어서 사용 가능!

<방명록 게시판 만드는 순서>
1.GuestbookMessage 객체 생성
2.Dao 객체 생성
3.Service 객체 생성 및 예외처리
4.jsp파일로 View 작성

1.GuestbookMessage 객체 생성

GuestbookMessage.java

package dto;

//자바빈 클래스
public class GuestbookMessage {
	private int messageId;
	private String guestName;
	private String password;
	private String message;
	
	//기본생성자(Constructor)
	public GuestbookMessage() {
		super();
		// TODO Auto-generated constructor stub
	}

	//생성자
	public GuestbookMessage(int messageId, String guestName, String password, String message) {
		super();
		this.messageId = messageId;
		this.guestName = guestName;
		this.password = password;
		this.message = message;
	}
	
	
	public int getMessageId() {
		return messageId;
	}

	public void setMessageId(int messageId) {
		this.messageId = messageId;
	}


	public String getGuestName() {
		return guestName;
	}


	public void setGuestName(String guestName) {
		this.guestName = guestName;
	}


	public String getPassword() {
		return password;
	}


	public void setPassword(String password) {
		this.password = password;
	}


	public String getMessage() {
		return message;
	}


	public void setMessage(String message) {
		this.message = message;
	}


	@Override
	public String toString() {
		return "GuestbookMessage [messageId=" + messageId + ", guestName=" + guestName + ", password=" + password
				+ ", message=" + message + "]";
	}
	
	
}

2.Dao 객체 생성

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 dto.GuestbookMessage;
import jdbc.JdbcUtil;

//Data Access Object
public class MessageDao {
	//싱글톤 패턴
	private static MessageDao instance = new MessageDao();
	public static MessageDao getInstance() {
		return instance;
	}
	private MessageDao() {}
	
	/**guestbook_message 테이블로 insert
	 * insert, update, delete 기본 return type은 int
	 * params : 커넥션 객체, 무엇을 입력할 것인지!(대상)
	 */
	public int insert(Connection conn, GuestbookMessage message) {
		//선언
		PreparedStatement pstmt = null;
		int result = 0;
		try {
			pstmt = conn.prepareStatement(
				"INSERT INTO GUESTBOOK_MESSAGE(MESSAGE_ID,GUEST_NAME,PASSWORD,MESSAGE)" + 
				" VALUES(" + 
				"    (SELECT NVL(MAX(MESSAGE_ID),0)+1 FROM GUESTBOOK_MESSAGE)" + 
				"    ,?,?,?" + 
				")"
			);
			pstmt.setString(1, message.getGuestName());
			pstmt.setString(2, message.getPassword());
			pstmt.setString(3, message.getMessage());
			return pstmt.executeUpdate();
		}catch(SQLException ex){
			ex.printStackTrace();
			return 0;
		}finally {
			//주의! 커넥션 객체는 비즈니스로직에서 닫음(Service)
			JdbcUtil.close(pstmt);
		}
	}//end insert
	
	//list.jsp의 메시지 목록
	public List<GuestbookMessage> selectList(Connection conn) throws SQLException {
		Statement stmt = null;
		ResultSet rs = null;
		
		try {
			//SELECT구문..
			String query = "SELECT MESSAGE_ID" + 
			"     , GUEST_NAME" + 
			"     , PASSWORD" + 
			"     , MESSAGE " + 
			" FROM   GUESTBOOK_MESSAGE" + 
			" ORDER BY MESSAGE_ID DESC";
			
			stmt = conn.createStatement();
			rs = stmt.executeQuery(query);
			//커서가 다음행으로 바라봤을 때 데이터가 있다면 실행
			if(rs.next()) {
				List<GuestbookMessage> messageList = new ArrayList<GuestbookMessage>();
				
				do {
					GuestbookMessage vo = new GuestbookMessage();
					vo.setMessageId(rs.getInt("MESSAGE_ID"));
					vo.setGuestName(rs.getString("GUEST_NAME"));
					vo.setPassword(rs.getString("PASSWORD"));
					vo.setMessage(rs.getString("MESSAGE"));
					//message_id는 자료형이 int이므로 getInt()로 받는다
					
					messageList.add(vo);
				}while(rs.next());
				return messageList;
			}else { //select 결과 없을 때
				return Collections.emptyList();
			}//end if
		}finally {
			JdbcUtil.close(rs);
			JdbcUtil.close(stmt);
		}
	}
	
	//메시지 수정(커넥션, 무엇을)
	public int update(Connection conn, GuestbookMessage message) {
		PreparedStatement pstmt = null;
		
		try {
			pstmt = conn.prepareStatement("UPDATE GUESTBOOK_MESSAGE" +
					" SET GUEST_NAME = ?, MESSAGE = ?" +
					" WHERE MESSAGE_ID = ? AND PASSWORD = ?");
			pstmt.setString(1, message.getGuestName());
			pstmt.setString(2, message.getMessage());
			pstmt.setInt(3, message.getMessageId());
			pstmt.setString(4, message.getPassword());
			
			return pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
			return 0;
		}finally {
			JdbcUtil.close(pstmt);
			//커넥션 객체는 서비스단에서 close해준다.
		}//end try
	}
	
	//삭제 : conn은 db연결, message는 삭제할 대상 지정
	public int delete(Connection conn, GuestbookMessage message) {
		PreparedStatement pstmt = null;
		
		try {
			pstmt = conn.prepareStatement("DELETE FROM GUESTBOOK_MESSAGE" +
					" WHERE MESSAGE_ID = ?");
			pstmt.setInt(1, message.getMessageId());
			
			return pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
			return 0;
		}finally {
			JdbcUtil.close(pstmt);
		}
	}
}

3.Service 객체 생성 및 예외처리

WriteMessageService.java

package guestbook.service;

import java.sql.Connection;
import java.sql.SQLException;

import dto.GuestbookMessage;
import guestbook.dao.MessageDao;
import jdbc.ConnectionProvider;
import jdbc.JdbcUtil;
//***Service.java => 비즈니스(기능) 로직
public class WriteMessageService {
	//싱글톤 패턴 적용
	private static WriteMessageService instance = new WriteMessageService();
	public static WriteMessageService getInstance() {
		return instance;
	}
	private WriteMessageService() {}
	
	//방명록 insert
	public void write(GuestbookMessage message) {
		//커넥션 객체를 선언(DBCP에서 가져온 커넥션)
		Connection conn = null;
		try {
			//DBCP 커넥션 객체를 생성
			conn = ConnectionProvider.getConnection();
			//guestbook_message테이블로 insert => Data Access Object 영역
			MessageDao messageDao = MessageDao.getInstance();
			int result = messageDao.insert(conn, message);
		}catch(SQLException ex) {
			throw new ServiceException("메시지 등록 실패 : " + ex.getMessage(), ex);
		}finally {
			JdbcUtil.close(conn);
		}
	}
	
}

GetMessageListService.java

package guestbook.service;

public class ServiceException extends RuntimeException {
	
	//생성자
	public ServiceException(String message, Exception cause) {
		super(message, cause);
	}
	//생성자
	public ServiceException(String message) {
		super(message);
	}
}

UpdateMessageService.java

package guestbook.service;

import java.sql.Connection;
import java.sql.SQLException;

import dto.GuestbookMessage;
import guestbook.dao.MessageDao;
import jdbc.ConnectionProvider;
import jdbc.JdbcUtil;

public class UpdateMessageService {
	//싱글톤 패턴
	private static UpdateMessageService instance = new UpdateMessageService(); 
	public static UpdateMessageService getInstance() {
		return instance;
	}
	private UpdateMessageService() {}
	
	//메시지를 update하는 비즈니스 로직
	public int update(GuestbookMessage message) {
		Connection conn = null;
		int result = 0;
		try {
			conn = ConnectionProvider.getConnection();
			//DAO 객체 생성
			MessageDao messageDao = MessageDao.getInstance();
			result = messageDao.update(conn, message);
			
		}catch(SQLException ex) {
			throw new ServiceException("메시지 수정 실패 : " + ex.getMessage(), ex);
		}finally {
			JdbcUtil.close(conn);
		}
		return result;
	}
}

DeleteMessageService.java

package guestbook.service;

import java.sql.Connection;
import java.sql.SQLException;

import dto.GuestbookMessage;
import guestbook.dao.MessageDao;
import jdbc.ConnectionProvider;
import jdbc.JdbcUtil;

public class DeleteMessageService {
	//new를 사용하면 요청할 때마다 객체가 생성되어 과부하가 되므로 싱글톤을 사용한다.
	
	private static DeleteMessageService instance = new DeleteMessageService();
	public static DeleteMessageService getInstance() {
		return instance;
	}
	private DeleteMessageService() {}
	//데이터 삭제
	public int delete(GuestbookMessage message) {
		Connection conn = null;
		
		try {
			conn = ConnectionProvider.getConnection();
			
			MessageDao messageDao = MessageDao.getInstance();
			
			int result = messageDao.delete(conn, message);
			return result;
			
		} catch (SQLException ex) {
			//삭제 시 문제가 발생되면 롤백 처리
			//DC(control)L : commit, rollback(마지막 커밋 시점으로 돌아감)
			// -> 트랜잭션이 종료가 되는 동시에 새로운 트랜잭션이 시작
			// -> 트랜잭션? DB를 변경하기 위해 수행되어야 할 논리적 단위(여러개의 sql로 구성)
			JdbcUtil.rollback(conn);
			throw new ServiceException("삭제 실패", ex);
		}finally {
			JdbcUtil.close(conn);
		}
	}
}

ServiceException.java

package guestbook.service;

public class ServiceException extends RuntimeException {
	
	//생성자
	public ServiceException(String message, Exception cause) {
		super(message, cause);
	}
	//생성자
	public ServiceException(String message) {
		super(message);
	}
}

4.jsp파일로 View 작성

list.jsp

<%@page import="guestbook.service.GetMessageListService"%>
<%@ page import="dto.GuestbookMessage"%>
<%@ page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%
//list.jsp에서  사용할
//메시지 목록(List<GuestbookMessage>)을 가져와주는 서비스 로직
GetMessageListService messageListService = GetMessageListService.getInstance();
List<GuestbookMessage> list = messageListService.getMessageList();
%>
<c:set var="list" value="<%=list%>" />
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="/js/jquery-3.6.0.js"></script>
<title>방명록 메시지 목록</title>
<script type="text/javascript">
$(function(){
//	alert("왔다!");
});

//fn_updt(기본키, 작성자 , 메시지)
function fn_updt(vara, varb, varc){
	//alert(vara);
	//기본키 데이터를 vara 매개변수로 받아서 frmUpdate 폼의 기본키 데이터로 사용
	$("#messageId").val(vara);
	//작성자 매개변수를 frmUpdate 폼의 이름 데이터로 사용
	$("#guestName").val(varb);
	//메시지 매개변수를 frmUpdate 폼의 내용 데이터로 사용
	$("#message").val(varc);
	$("#frmWrite").css("display","none");
	$("#frmUpdate").css("display","block");
}
</script>
</head>
<body>
<form id="frmWrite" method="post" action="writeMessage.jsp" style="display:block;">
	이름 : <input type="text" name="guestName"/><br>
	비밀번호 : <input type="password" name="password"/><br>
	내용 : <textarea rows="3" cols="30" name="message"></textarea><br>
	<input type="submit" value="메시지 남기기" />
</form>
<form id="frmUpdate" method="post" action="updateMessage.jsp" style="display:none;">
	<input type="hidden" name="messageId" id="messageId" />
	이름 : <input type="text" name="guestName" id="guestName"/><br>
	비밀번호 : <input type="password" name="password"/><br>
	내용 : <textarea rows="3" cols="30" name="message" id="message"></textarea><br>
	<input type="submit" value="확인" />&nbsp;
	<input type="button" value="취소" onclick="javascript:location.href='list.jsp';"/>
</form>
<hr>

<!-- 
[수정]
1. 클릭 시 상단의 폼에 정보가 입력되고(비밀번호 제외)
	"메시지 남기기" 버튼이 hidden, "확인" 및 "취소" 버튼이 block
2. "확인" 클릭 시 해당 정보가 업데이트가 되는데, 이때 비밀번호가 일치해야 함
3. "취소" 클릭 시 현재 페이지의 목록으로 되돌아감
	"메시지 남기기" 버튼이 block, "확인" 및 "취소" 버튼이 hidden	

 -->
<c:if test="${param.result eq 1}">
	<div style="color:red;">변경 성공했습니다.</div>
</c:if>
<c:if test="${param.result < 1}">
	<div style="color:red;">비밀번호를 확인해주세요.</div>
</c:if>
<table border="1">
<c:forEach var="message" items="${list}">
	<tr>
		<td>
			메시지   번호 : <span>${message.messageId}</span><br>
			손  님  이  름 : <span>${message.guestName}</span><br>
			메     시    지 : <span>${message.message}</span><br>
			<a href="#" id="updt" onclick="fn_updt('${message.messageId}','${message.guestName}','${message.message}')">[수정]</a>&nbsp;
			<a href="deleteMessage.jsp?messageId=${message.messageId}">[삭제]</a>
		</td>
	</tr>
</c:forEach>
</table>
</body>
</html>

writeMessage.jsp

<%@page import="guestbook.service.WriteMessageService"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
	request.setCharacterEncoding("UTF-8");
%>
<!DOCTYPE html>
<html>
<head>
<title>방명록 메시지 남김</title>
</head>
<body>
<jsp:useBean id="guestbookMessage" class="dto.GuestbookMessage">
	<jsp:setProperty name="guestbookMessage" property="*" />
	<!-- request로 넘어온 모든 데이터를  guestbookMessage 이름으로 매핑한다-->
</jsp:useBean>
${guestbookMessage.messageId}<br>
${guestbookMessage.guestName}<br>
${guestbookMessage.password}<br>
${guestbookMessage.message}<br>
<%
	//싱글톤 패턴
	WriteMessageService writeMessageService = WriteMessageService.getInstance();
	writeMessageService.write(guestbookMessage);
%>
방명록에 메시지를 남겼습니다.
<a href="list.jsp">[목록보기]</a>
</body>
</html>

updateMessage.jsp

<%@page import="dto.GuestbookMessage"%>
<%@page import="guestbook.service.UpdateMessageService"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%
request.setCharacterEncoding("UTF-8");

String messageId = request.getParameter("messageId");
String guestName = request.getParameter("guestName");
String password = request.getParameter("password");
String message = request.getParameter("message");


out.print("messageId : " + messageId + "<br>");
out.print("guestName : " + guestName + "<br>");
out.print("password : " + password + "<br>");
out.print("message : " + message + "<br>");

//getter 안쓰는 대신 생성자 파라미터에 이렇게 넣는다!
GuestbookMessage guestbookmessage = new GuestbookMessage(Integer.parseInt(messageId), guestName, password, message);

//여기서 사용할 UpdateMessageService의 객체를 생성
UpdateMessageService service = UpdateMessageService.getInstance();
int result = service.update(guestbookmessage);
if(result>0){ //변경 성공
	out.print("<script type='text/javascript'>location.href='list.jsp?result=1'</script>");
}else{ //변경 실패
	out.print("<script type='text/javascript'>location.href='list.jsp?result=0'</script>");
}

%>

deleteMessage.jsp

<%@page import="guestbook.service.ServiceException"%>
<%@page import="dto.GuestbookMessage"%>
<%@page import="guestbook.service.DeleteMessageService"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
	request.setCharacterEncoding("UTF-8");
	
	//list.jsp에서 보낸 파라미터 받기 -> request.getParameter로 받으면 무조건 String형
	String messageId = request.getParameter("messageId");
	
	GuestbookMessage message = new GuestbookMessage();
	//int messageId 멤버변수(String messageId)로 형변환
	message.setMessageId(Integer.parseInt(messageId));
	//삭제 성공 여부(성공으로 세팅)
	boolean result = true;
	
	//삭제된 건수
	int cnt = 0;
	
	try{
		DeleteMessageService service = DeleteMessageService.getInstance();
		cnt = service.delete(message);
	}catch(ServiceException ex){ //서비스에서 throw new ServiceException으로 던진거 받기
		//실패 처리
		result = false;
	}

%>
<!DOCTYPE html>
<html>
<head>
<title>방명록 메시지 삭제</title>
</head>
<body>
<%
if(result){ //result : true일 때 
	if(cnt>0){ //삭제가 잘 된 경우
		out.print("메시지를 삭제하였습니다.");
	}else{ //기본키에 해당되는 데이터가 없을 경우
		out.print("해당 데이터가 없습니다.");
	}
}else{ //result : false
	out.print("삭제가 되지 않았습니다.");
}
%>
<br>
<a href="list.jsp">[목록 보기]</a>
</body>
</html>

JSP - Service - Dao - Oracle
l          l          l          l
view            Model
사용자      비즈니스 로직
영역

Controller는 View의 요청과 Model의 응답을 처리한다

Spring -> Spring Boot(스프링을 더 쉽게 이용하기 위한 도구)

프레임워크 : 디자인패턴(view, model) + 라이브러리(jar)

카멜 표기 변환


create or replace FUNCTION FN_GETCAMEL(COLUMN_NAME IN VARCHAR2)
RETURN VARCHAR2
IS
RSLT VARCHAR2(30);
BEGIN
--카멜표기로 변환(SITE_NUM -> siteNum)
SELECT LOWER(SUBSTR(REPLACE(INITCAP(COLUMN_NAME),'_'),1,1))
|| SUBSTR(REPLACE(INITCAP(COLUMN_NAME),'_'),2) INTO RSLT
FROM DUAL;
--리턴
RETURN RSLT;
END;
/

--구글 카멜변환(https://heavenly-appear.tistory.com/270)
SELECT COLUMN_NAME
, DATA_TYPE
, CASE WHEN DATA_TYPE='NUMBER' THEN 'private int ' || FN_GETCAMEL(COLUMN_NAME) || ';'
WHEN DATA_TYPE IN('VARCHAR2','CHAR') THEN 'private String ' || FN_GETCAMEL(COLUMN_NAME) || ';'
WHEN DATA_TYPE='DATE' THEN 'private Date ' || FN_GETCAMEL(COLUMN_NAME) || ';'
ELSE 'private String ' || FN_GETCAMEL(COLUMN_NAME) || ';'
END AS CAMEL_CASE
, '' RESULTMAP
FROM ALL_TAB_COLUMNS
WHERE TABLE_NAME = 'CUS';

0개의 댓글