JSP

[JSP] JBDC

shb 2022. 4. 6. 15:17

JDBC 연결 + 게시판 작성

게시판 설계
1. 게시판 CRUD 사이클
 글생성 - 글목록 보기 - 글내용 읽기 - 글수정 - 글 삭제
2. 글 작성시 ‘작성자’ 와 ‘글제목’ 은 *필수*
   조회수 구현

 

* MySql 용 쿼리

SET SESSION FOREIGN_KEY_CHECKS=0;

/* Drop Tables */

DROP TABLE IF EXISTS test_write;




/* Create Tables */

CREATE TABLE test_write
(
	wr_uid int NOT NULL AUTO_INCREMENT,
	wr_subject varchar(200) NOT NULL,
	wr_content text,
	wr_name varchar(20) NOT NULL,
	wr_viewcnt int DEFAULT 0,
	wr_regdate datetime DEFAULT now(),
	PRIMARY KEY (wr_uid)
);


SELECT * FROM test_write;

-- 기본데이터 삽입
INSERT INTO test_write
	(wr_subject, wr_content, wr_name)
VALUES
	('첫째글:방가요', '안녕하세요', '김희철'),
	('둘째글:헤헤헤','1111', '김수길'),
	('세째글:힘내세요', '7394', '최진덕'),
	('네째글: ... ', '9090', '이혜원'),
	('다섯째글: 게시판', '7531', '박수찬')
;

SELECT * FROM test_write ORDER BY wr_uid DESC;

SELECT wr_uid uid, wr_subject subject, wr_content content,
	wr_name name, wr_viewcnt viewcnt, wr_regdate regdate
FROM test_write ORDER BY wr_uid DESC;	

 

 

해당 DB의 JDBC 라이브러리 설치
반드시 해당 jar 파일을 webapp/ WEB-INF / lib 폴더에 붙여 넣기.

 

JDBC 연동 순서
1. JDBC 드라이버 로딩 : Class.forName(“드라이버 클래스”);
2. 데이터베이스 연결 (Connection 객체 생성) :  DriverManager.getConnection() 
3. Statement 객체 생성 :  위 Connection 객체의 createStatement();
   (혹은) PreparedStatement 객체 생성  : 위 Connection 객체의 PreparedStatement();
4. 위 Statement/PreparedStatement 객체로부터 SQL 쿼리 실행
   a. executeQuery() :  SELECT 쿼리 수행 → ResultSet 리턴
   b. executeUpdate() : INSERT, UPDATE, DELETE (DML) 쿼리 수행 → int 리턴
5. ResultSet객체로부터 데이터 추출,  ( SELECT 쿼리의 경우)
   a. row 관련 메소드: next(), previous(), first(), last(), …
   b. 컬럼값 추출 메소드 : getString(), getInt(), getXXX()  ….
6. 데이터베이스 자원 반납 close() : 
   a. ResultSet ,  Statement 혹은 PreparedStatement , Connection 을 close() 한다

 


- Connection 은 페이지당 (request 당) ‘한번만 생성하면’ 충분.
- 하나의 Connection 으로부터 복수개 Statement / PreparedStatement 생성하여 운용 가능.
- 기존에 생성된 PreparedStatement 참조변수에 새로은 PreparedStatement 를 생성받을 경우 기존의 객체를 미리 close() 해주자.  → (Resource Leak 위험)
- ResultSet 도 마찬가지.   동일 참조변수에 다시 받을 경우, 기존의 것을 close() 해주자

 

데이터베이스에서 트랜잭션 (transaction) 이란, ‘데이터 조작 동작의 단위’이다.
하나의 ‘데이터 조작 동작’을 하기 위해 한개 뿐 아니라, 여러개의 쿼리가 수행될수 도 있는 거다.
가령, 이번 예제의 경우
‘글 읽기 트랜잭션’ 의 경우  →  조회수 증가 + 글 내용 불러오기 두가지 쿼리가 수행되어야 하는 것이다
트랜잭션의 쿼리문 수행도중 쿼리 실패가 발생되면, 직전에 했었던 쿼리들을 원위치(rollback) 시켜야  한다.


JSP 파일 생성

write.jsp     ←  작성  form
writeOk.jsp ←  작성  완료  ( INSERT )
list.jsp    ← 리스트(목록)   ( SELECT )
view.jsp    ← 항목 보기(항목)  ( SELECT, UPDATE )
update.jsp     ←  수정 form   ( SELECT )
updateOk.jsp  ←  수정 완료  ( UPDATE )
deleteOk.jsp  ←  삭제 완료  ( DELETE )
db_test.jsp   ←  커넥션 테스트 및 (기본 코드) 용

 

 

* db_test.jsp  커넥션 테스트 및 (기본 코드) 용

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import = "java.sql.*" %>  <%-- JDBC 관련 클래스 import --%>
<%!
	// JDBC 관련 기본 객체 변수들 선언
	Connection conn = null;
	Statement stmt = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;    // executeQuery(), SELECT 결과
	int cnt = 0;            // executeUpdate(), DML 결과
	
	// Connection 에 필요한 값
	// MySQL 8.x 
	final String DRIVER = "com.mysql.cj.jdbc.Driver";   
	final String URL = "jdbc:mysql://localhost:3306/mydb111";  // DB접속 URL
	final String USERID = "myuser111";
	final String USERPW = "1234";
%>
<%!
	// 쿼리문 준비
	// TODO
%>
<%
	Class.forName(DRIVER);  // 드라이버 로딩
	out.println("드라이버 로딩 성공<br>");
	conn = DriverManager.getConnection(URL, USERID, USERPW);
	out.println("conn 성공<br>");
	
	// 트랜잭션 실행
	// TODO
	
	// 리소스 해제
	if(rs != null) rs.close();
	if(stmt != null) stmt.close();
	if(pstmt != null) pstmt.close();
	if(conn != null) conn.close();
%>

 

* write.jsp  : 작성  form

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js"></script>
    <title>작성</title>
</head>

<body>
    <div class="container mt-3">
        <h2>작성</h2>
        <hr>
        <form action="writeOk.jsp" method="POST">
            <div class="mb-3">
                <label for="name">작성자:</label>
                <input type="text" class="form-control" id="name" placeholder="작성자를 입력하세요" name="name" required>
            </div>
            <div class="mb-3 mt-3">
                <label for="subject">제목:</label>
                <input type="text" class="form-control" id="subject" placeholder="제목을 입력하세요" name="subject" required>
            </div>
            <div class="mb-3 mt-3">
                <label for="content">내용:</label>
                <textarea class="form-control" rows="5" id="content" placeholder="내용을 입력하세요" name="content"></textarea>
            </div>

            <button type="submit" class="btn btn-outline-dark">작성완료</button>
            <a class="btn btn-outline-dark" href="list.jsp">목록</a>
        </form>

    </div>

</body>

</html>

 

* writeOk.jsp  작성 완료 ( INSERT )

write.jsp 로부터 작성한 글 데이터들을 parameter 로 받아서 INSERT 트랜잭션 수행
트랜잭션만 수행하고 view.jsp 로 넘어갈거기 때문에 html 코드는 필요없으니 삭제 
이미 만들어 놓은 db_test.jsp 의 내용을 그대로 복사

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import = "java.sql.*" %>  <%-- JDBC 관련 클래스 import --%>
<%
	request.setCharacterEncoding("utf-8");  // POST 한글 인코딩 꼭!
	// 입력한 값 받아오기
	String name = request.getParameter("name");
	String subject = request.getParameter("subject");
	String content = request.getParameter("content");
	
	// 유효성 체크.  null 이거나, 빈 문자열이면 이전화면으로 돌아가기
	if(name == null || subject == null || name.trim().equals("") || subject.trim().equals("")){
%>
		<script>
			alert("작성자이름, 글제목을 입력하세요!!!");
			history.back();
		</script>
<%	
		return;     // ★ 더이상 JSP 프로세싱 하지 않도록 여기서 종료★
	} // end if
%>
<%!
	// JDBC 관련 기본 객체 변수들 선언
	Connection conn = null;
	Statement stmt = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;    // executeQuery(), SELECT 결과
	int cnt = 0;            // executeUpdate(), DML 결과
	
	// Connection 에 필요한 값
	// MySQL 8.x 
	final String DRIVER = "com.mysql.cj.jdbc.Driver";   
	final String URL = "jdbc:mysql://localhost:3306/mydb111";  // DB접속 URL
	final String USERID = "myuser111";
	final String USERPW = "1234";
%>
<%!
	// 쿼리문 준비
	final String SQL_WRITE_INSERT = "INSERT INTO test_write" + 
			"(wr_subject, wr_content, wr_name) " + 
			"VALUES(?, ?, ?)";

	int uid;  // auto-generated keys 값 (wr_uid 컬럼값)
%>
<%
	Class.forName(DRIVER);  // 드라이버 로딩
	out.println("드라이버 로딩 성공<br>");
	conn = DriverManager.getConnection(URL, USERID, USERPW);
	out.println("conn 성공<br>");
	
	// auto-generated 컬럼
	String [] generatedCols = {"wr_uid"};
	
	// 트랜잭션 실행
	pstmt = conn.prepareStatement(SQL_WRITE_INSERT, generatedCols);
	pstmt.setString(1, subject);
	pstmt.setString(3, content);
	pstmt.setString(3, name);
	
	cnt = pstmt.executeUpdate();
	
	if(cnt > 0){
		// auto-generated 값 뽑아오기
		rs = pstmt.getGeneratedKeys();
		if(rs.next()){
			uid = rs.getInt(1);
		}
	}
	
	
	// 리소스 해제
	if(rs != null) rs.close();
	if(stmt != null) stmt.close();
	if(pstmt != null) pstmt.close();
	if(conn != null) conn.close();
%>


<% if(cnt == 0){ %>
	<script>
		alert("등록 실패");
		history.back();
	</script>
<% } else { %>
	<script>
		alert("등록 성공");
		location.href = "view.jsp?uid=<%= uid %>";
	</script>
<% } %>

 

* list.jsp  : 리스트(목록) ( SELECT )

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import = "java.sql.*" %>  <%-- JDBC 관련 클래스 import --%>
<%@ page import = "java.time.*" %>
<%@ page import = "java.time.format.*" %>
<%!
	// JDBC 관련 기본 객체 변수들 선언
	Connection conn = null;
	Statement stmt = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;    // executeQuery(), SELECT 결과
	int cnt = 0;            // executeUpdate(), DML 결과
	
	// Connection 에 필요한 값
	// MySQL 8.x 
	final String DRIVER = "com.mysql.cj.jdbc.Driver";   
	final String URL = "jdbc:mysql://localhost:3306/mydb111";  // DB접속 URL
	final String USERID = "myuser111";
	final String USERPW = "1234";
%>
<%!
	// 쿼리문 준비
	final String SQL_WRITE_SELECT = 
		"SELECT wr_uid uid, wr_subject subject, wr_content content, " + 
		"wr_name name, wr_viewcnt viewcnt, wr_regdate regdate " + 
		"FROM test_write ORDER BY wr_uid DESC";
%>
<%
	int uid = 0;
	String name = "";
	String subject = "";
	String content = "";
	String regdate = "";
	int viewcnt = 0;
%>
<%
	Class.forName(DRIVER);  // 드라이버 로딩
	//out.println("드라이버 로딩 성공<br>");
	conn = DriverManager.getConnection(URL, USERID, USERPW);
	//out.println("conn 성공<br>");
	
	// 트랜잭션 실행
	pstmt = conn.prepareStatement(SQL_WRITE_SELECT);
	rs = pstmt.executeQuery();
%>
<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js"></script>

    <title>목록</title>
</head>

<body>

    <div class="container mt-3">
        <h2>목록</h2>
        <hr>
        
        <table class="table table-hover">
            <thead class="table-success">
                <tr>
                    <th>#</th>
                    <th>제목</th>
                    <th>작성자</th>
                    <th>조회수</th>
                    <th>작성일</th>
                </tr>
            </thead>
            <tbody>
<% while(rs.next()){ 
		uid = rs.getInt("uid");
		subject = rs.getString("subject");
		name = rs.getString("name");
		content = rs.getString("content");
		if(content == null) content = "";
		viewcnt = rs.getInt("viewcnt");
		
		LocalDateTime t = rs.getObject("regdate", LocalDateTime.class);
		regdate = t.format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
%>
                <tr>
                    <td><%= uid %></td>
                    <td><a href="view.jsp?uid=<%= uid %>"><%= subject %></a> </td>
                    <td><%= name %></td>
                    <td><%= viewcnt %></td>
                    <td><%= regdate %></td>
                </tr>
<% } %>
            </tbody>
        </table>
        <div class="row">
            <div class="col-12">
                <a class="btn btn-outline-dark" href="write.jsp">작성</a>
            </div>
        </div>
    </div>

</body>

</html>
		
<%
	// 리소스 해제
	if(rs != null) rs.close();
	if(stmt != null) stmt.close();
	if(pstmt != null) pstmt.close();
	if(conn != null) conn.close();
%>

 

* view.jsp  항목 보기(항목) ( SELECT, UPDATE )

목록에서 특정 글 제목을 클릭하면 글읽기 페이지로 이동
기본적으로 2가지 쿼리를 해야 한다
1. 조회수 증가!  (UPDATE)
2. 해당 글 내용 읽어오기 (SELECT)

하단 버튼 추가
[수정하기] → update.jsp 
[삭제하기] → deleteOk.jsp 
↑ uid 값과 함께 넘겨주어야 함

 

기본적으로 JDBC 프로그래밍은 Auto-Commit 되어 있다.  즉, 매 DML 쿼리 수행마다, 곧바로 DB에 반영된다.
그러나 여러개의 쿼리가 하나의 트랜잭션을 이루고 있다면,  중간에 쿼리 실패가 발생한 경우, 다시 원상 복귀가 되어야 한다.  즉, Auto-Commit 을 하면 안된다. 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import = "java.sql.*" %>  <%-- JDBC 관련 클래스 import --%>
<%@ page import = "java.time.*" %>
<%@ page import = "java.time.format.*" %>

<% // parameter 받아오기
	int uid = Integer.parseInt(request.getParameter("uid"));
	// ※ 이 단계에서 parameter 검증 필요
%>


<%!
	// JDBC 관련 기본 객체 변수들 선언
	Connection conn = null;
	Statement stmt = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;    // executeQuery(), SELECT 결과
	int cnt = 0;            // executeUpdate(), DML 결과
	
	// Connection 에 필요한 값
	// MySQL 8.x 
	final String DRIVER = "com.mysql.cj.jdbc.Driver";   
	final String URL = "jdbc:mysql://localhost:3306/mydb111";  // DB접속 URL
	final String USERID = "myuser111";
	final String USERPW = "1234";
%>
<%!
	// 쿼리문 준비
	// 조회수 증가
	final String SQL_WRITE_INC_VIEWCNT = "UPDATE test_write SET wr_viewcnt = wr_viewcnt + 1 WHERE wr_uid = ?";
	// 글 1개 읽어오기
	final String SQL_WRITE_SELECT_BY_UID = 
		"SELECT wr_uid uid, wr_subject subject, wr_content content, " + 
		"wr_name name, wr_viewcnt viewcnt, wr_regdate regdate " + 
		"FROM test_write WHERE wr_uid = ?";
%>
<%
	String name = "";
	String subject = "";
	String content = "";
	String regdate = "";
	int viewcnt = 0;
%>
<%
	try{		
		Class.forName(DRIVER);  // 드라이버 로딩
		//out.println("드라이버 로딩 성공<br>");
		conn = DriverManager.getConnection(URL, USERID, USERPW);
		//out.println("conn 성공<br>");
		
		// 여러 쿼리문이 하나의 트랜잭션으로 동작하기 위해서
		conn.setAutoCommit(false);   // 일단 auto-commit 을 false
		
		// 1. 조회수 증가 쿼리
		pstmt = conn.prepareStatement(SQL_WRITE_INC_VIEWCNT);
		pstmt.setInt(1, uid);
		cnt = pstmt.executeUpdate();
		// ※ cnt 결과값에 따른 처리 필요
		
		pstmt.close();
			
		// 2. uid   의 글 읽어오기 쿼리
		pstmt = conn.prepareStatement(SQL_WRITE_SELECT_BY_UID);
		pstmt.setInt(1, uid);
		rs = pstmt.executeQuery();
		
		// 한개의 레코드만 select 된다.
		if(rs.next()){
			uid = rs.getInt("uid");
			subject = rs.getString("subject");
			name = rs.getString("name");
			content = rs.getString("content");
			if(content == null) content = "";
			viewcnt = rs.getInt("viewcnt");
			
			LocalDateTime t = rs.getObject("regdate", LocalDateTime.class);
			regdate = t.format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
			
			
		} else {
			// 해당 wr_uid 의 글이 없다 (이미 지워졌든지, 없는 uid  이든지..)
%>
			<script>
				alert("해당 정보가 삭제되거나 없습니다");
				history.back();
			</script>
<%		
			return;
		}
		
		conn.commit();  // 모든 쿼리가 성공하면 비로서 commit 하여 트랜잭션 종료.
	} catch(Exception e) {
		conn.rollback();  // 트래잭션 중간에 실패하면 rollback 한다.
		throw e;  // 발생한 예외는 서버쪽으로 넘김.
	} finally {
		// 리소스 해제
		if(rs != null) rs.close();
		if(stmt != null) stmt.close();
		if(pstmt != null) pstmt.close();
		if(conn != null) conn.close();		
	}

	
%>

<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js"></script>

    <title>조회 - <%= subject %></title>
</head>

<script>
function chkDelete(){
	var answer = confirm("삭제하시겠습니까?");
	if(answer){
		document.forms['frmDelete'].submit();
	}
}

</script>

<body>
    <div class="container mt-3">
        <h2>조회 - <%= subject %></h2>
        <hr>
        <div class="mb-3 mt-3 clearfix">
            <span class="float-start me-2">uid: <%= uid %></span>
            <span class="float-end ms-4">작성일: <%= regdate %></span>
            <span class="float-end">조회수: <%= viewcnt %></span>
        </div>

        <section>
        	<form name="frmDelete" action="deleteOk.jsp" method="POST">
        		<input type="hidden" name="uid" value="<%= uid %>">
        	</form>
            <div class="mb-3">
                <label for="name">작성자:</label>
                <div class="border bg-light rounded p-2" ><%= name %></div>
            </div>    
            <div class="mb-3 mt-3">
                <label for="subject">제목:</label>
                <div class="border bg-light rounded p-2" ><%= subject %></div>
            </div>    
            <div class="mb-3 mt-3">
                <label for="content">내용:</label>
                <div class="border bg-light rounded p-2" ><%= content %></div>
            </div>    

            <a class="btn btn-outline-dark" href="update.jsp?uid=<%= uid %>">수정</a>
            <a class="btn btn-outline-dark" href="list.jsp">목록</a>
            <button type="button" class="btn btn-outline-dark" onclick="chkDelete()">삭제</button>
            <a class="btn btn-outline-dark" href="write.jsp">작성</a>

        </section>
    </div>
</body>

</html>

 

* update.jsp 수정 form (SELECT)

기존의 글 내용을 읽어 들어와 보여주어야 한다 → view.jsp 와 비슷
그러나, 수정 가능하게 form 에 담아 보여주어야 함

[수정] 완료 submit 을 하려 하면,  새로 작성할때와 마찬가지로
form 유효성 검사 해주어야 한다  → write.jsp 와 비슷

 

<input type="hidden" ~ > 보여주긴 보여주되,  form 에 담아서 보여주어야 한다.
이때, 최초 작성후 변경되어서는 안되는 것도 있고, 변경할수 있는 것도 있다.
이번 예제에선 ‘작성자’ 는 변경 불가 로 한다. 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import = "java.sql.*" %>  <%-- JDBC 관련 클래스 import --%>
<%@ page import = "java.time.*" %>
<%@ page import = "java.time.format.*" %>

<%--
	CRUD 에서 Update 가. 가장 작성양이 많다.
	
	일단, 기존의 데이터를 불러 들어 와야 한다. SELECT
	그리고, 편집가능한 영역과 그렇지 않은 영역을 분리해서 사용자에게 form 을 제공해야 한다.
	표시내용은 view.jsp 에서 비슷하게 시작가능
	
	나중에 updateOk.jsp 로 넘겨서 실제 UPDATE 쿼리를 실행하기 위해선 uid 값도 넘어가야 한다.
	그래서 넘겨 받은 uid 값을 hidden 으로 담아 두었다가 넘겨준다.
	
 --%>

<% // parameter 받아오기
	int uid = Integer.parseInt(request.getParameter("uid"));
	// ※ 이 단계에서 parameter 검증 필요
%>

<%!
	// JDBC 관련 기본 객체 변수들 선언
	Connection conn = null;
	Statement stmt = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;    // executeQuery(), SELECT 결과
	int cnt = 0;            // executeUpdate(), DML 결과
	
	// Connection 에 필요한 값
	// MySQL 8.x 
	final String DRIVER = "com.mysql.cj.jdbc.Driver";   
	final String URL = "jdbc:mysql://localhost:3306/mydb111";  // DB접속 URL
	final String USERID = "myuser111";
	final String USERPW = "1234";
%>
<%!
	// 쿼리문 준비
	// 글 1개 읽어오기
	final String SQL_WRITE_SELECT_BY_UID = 
		"SELECT wr_uid uid, wr_subject subject, wr_content content, " + 
		"wr_name name, wr_viewcnt viewcnt, wr_regdate regdate " + 
		"FROM test_write WHERE wr_uid = ?";
%>
<%
	String name = "";
	String subject = "";
	String content = "";
	String regdate = "";
	int viewcnt = 0;
%>
<%
	Class.forName(DRIVER);  // 드라이버 로딩
	//out.println("드라이버 로딩 성공<br>");
	conn = DriverManager.getConnection(URL, USERID, USERPW);
	//out.println("conn 성공<br>");
	
	// 트랜잭션 실행
	pstmt = conn.prepareStatement(SQL_WRITE_SELECT_BY_UID);
	pstmt.setInt(1, uid);
	rs = pstmt.executeQuery();
	
	// 한개의 레코드만 select 된다.
	if(rs.next()){
		uid = rs.getInt("uid");
		subject = rs.getString("subject");
		name = rs.getString("name");
		content = rs.getString("content");
		if(content == null) content = "";
		viewcnt = rs.getInt("viewcnt");
		
		LocalDateTime t = rs.getObject("regdate", LocalDateTime.class);
		regdate = t.format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
		
		
	} else {
		// 해당 wr_uid 의 글이 없다 (이미 지워졌든지, 없는 uid  이든지..)
%>
		<script>
			alert("해당 정보가 삭제되거나 없습니다");
			history.back();
		</script>
<%		
		return;
	}
	
	
	// 리소스 해제
	if(rs != null) rs.close();
	if(stmt != null) stmt.close();
	if(pstmt != null) pstmt.close();
	if(conn != null) conn.close();
%>

<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js"></script>

    <title>수정 - <%= subject %></title>
</head>


<body>
    <div class="container mt-3">
        <h2>수정</h2>
        <hr>
        <div class="mb-3 mt-3 clearfix">
            <span class="float-start me-2">uid: <%= uid %></span>
            <span class="float-end ms-4">작성일: <%= regdate %></span>
            <span class="float-end">조회수: <%= viewcnt %></span>
        </div>

        <form name="frm" action="updateOk.jsp" method="post">
            <input type="hidden" name="uid" value="<%= uid %>"/>
            <div class="mb-3">
                <label for="name">작성자:</label>
                <div class="border bg-light rounded p-2" ><%= name %></div>
            </div>    
            <div class="mb-3 mt-3">
                <label for="subject">제목:</label>
                <input type="text" class="form-control" id="subject" placeholder="제목을 입력하세요" name="subject" value="<%= subject %>" required>
            </div>
            <div class="mb-3 mt-3">
                <label for="content">내용:</label>
                <textarea class="form-control" rows="5" id="content" placeholder="내용을 입력하세요" name="content"><%= content %></textarea>
            </div>


            <button type="submit" class="btn btn-outline-dark">수정완료</button>
            <button type="button" class="btn btn-outline-dark" onclick="history.back()">이전으로</button>
            <a class="btn btn-outline-dark" href="list.jsp">목록</a>

        </form>
    </div>
</body>

</html>

 

* updateOk.jsp - 수정완료( UPDATE )

update.jsp 에서 수정완료 → UPDATE 트랜잭션 발생
수정 완료후에는 view.jsp 로 넘어가자

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import = "java.sql.*" %>  <%-- JDBC 관련 클래스 import --%>
<% // parameter 받아오기
	request.setCharacterEncoding("utf-8");  // POST 방식 한글 인코딩 꼭!
	int uid = Integer.parseInt(request.getParameter("uid"));
	String subject = request.getParameter("subject");
	String content = request.getParameter("content");
	// ※ 사실 이단계에서 parameter 검증 필요
%>
<%!
	// JDBC 관련 기본 객체 변수들 선언
	Connection conn = null;
	Statement stmt = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;    // executeQuery(), SELECT 결과
	int cnt = 0;            // executeUpdate(), DML 결과
	
	// Connection 에 필요한 값
	// MySQL 8.x 
	final String DRIVER = "com.mysql.cj.jdbc.Driver";   
	final String URL = "jdbc:mysql://localhost:3306/mydb111";  // DB접속 URL
	final String USERID = "myuser111";
	final String USERPW = "1234";
%>
<%!
	// 쿼리문 준비
	final String SQL_WRITE_UPDATE
		= "UPDATE test_write SET wr_subject = ?, wr_content = ? WHERE wr_uid = ?";
%>
<%
	Class.forName(DRIVER);  // 드라이버 로딩
	//out.println("드라이버 로딩 성공<br>");
	conn = DriverManager.getConnection(URL, USERID, USERPW);
	//out.println("conn 성공<br>");
	
	// 트랜잭션 실행
	pstmt = conn.prepareStatement(SQL_WRITE_UPDATE);
	
	pstmt.setString(1, subject);
	pstmt.setString(2, content);
	pstmt.setInt(3, uid);
	
	cnt = pstmt.executeUpdate();
	
	// 리소스 해제
	if(rs != null) rs.close();
	if(stmt != null) stmt.close();
	if(pstmt != null) pstmt.close();
	if(conn != null) conn.close();
%>

<% if(cnt == 0){ %>
	<script>
		alert("수정 실패");
		history.back();
	</script>
<% } else { %>
	<script>
		alert("수정 성공");
		location.href = "view.jsp?uid=<%= uid %>";
	</script>
<% } %>

 

* deleteOk.jsp - 삭제 완료 ( DELETE)

삭제하기 전엔 한번은 ‘확인’ 시켜 주는 게 좋다.  → view.jsp 에서 작성
삭제 성공 후에는 list.jsp 로 이동.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import = "java.sql.*" %>  <%-- JDBC 관련 클래스 import --%>
<% // parameter 받아오기
	int uid = Integer.parseInt(request.getParameter("uid"));
	// ※ 이 단계에서 parameter 검증 필요
%>
<%!
	// JDBC 관련 기본 객체 변수들 선언
	Connection conn = null;
	Statement stmt = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;    // executeQuery(), SELECT 결과
	int cnt = 0;            // executeUpdate(), DML 결과
	
	// Connection 에 필요한 값
	// MySQL 8.x 
	final String DRIVER = "com.mysql.cj.jdbc.Driver";   
	final String URL = "jdbc:mysql://localhost:3306/mydb111";  // DB접속 URL
	final String USERID = "myuser111";
	final String USERPW = "1234";
%>
<%!
	// 쿼리문 준비
	final String SQL_WRITE_DELETE_BY_UID = "DELETE FROM test_write WHERE wr_uid = ?";
%>
<%
	Class.forName(DRIVER);  // 드라이버 로딩
	//out.println("드라이버 로딩 성공<br>");
	conn = DriverManager.getConnection(URL, USERID, USERPW);
	//out.println("conn 성공<br>");
	
	// 트랜잭션 실행
	pstmt = conn.prepareStatement(SQL_WRITE_DELETE_BY_UID);
	pstmt.setInt(1, uid);
	cnt = pstmt.executeUpdate();
	
	// 리소스 해제
	if(rs != null) rs.close();
	if(stmt != null) stmt.close();
	if(pstmt != null) pstmt.close();
	if(conn != null) conn.close();
%>

<% if(cnt == 0){ %>
	<script>
		alert("삭제 실패");
		history.back();
	</script>
<% } else { %>
	<script>
		alert("삭제 성공");
		location.href = "list.jsp";
	</script>
<% } %>

 

* 페이지 코드 작성 흐름 

일반적인 웹프로그래밍은 하나의 페이지에 대한 request가 발생하면 다음과 같은 흐름으로 코드를 작성합니다.
가급적, 이  흐름이 명확히 구분이 되는 것이 좋습니다  → 유지보수, 가독성 차원 고려

 

  Parameter 받아오기, 유효성 검증

                  ↓
페이지에 필요한 데이터 처리, 트랜잭션

                  ↓
      결과 출력 (HTML 작성)

'JSP' 카테고리의 다른 글

[JSP] MVC model2  (0) 2022.04.06
[JSP] DAO, DTO  (0) 2022.04.06
[JSP] 자바 빈  (0) 2022.04.05
[JSP] 세션(Session)  (0) 2022.03.31
[JSP] 쿠키  (0) 2022.03.25