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 |