이제 등록을 해보자. 입력 화면도 만들도 등록 Servlet도 만들고 Transaction도 살펴보자. 하지만 늘 그렇듯 Transaction은 맛만 보자..;
1. 목표
회원등록 화면을 만들고 Servlet으로 Insert SQL을 수행하고 회원 목록 화면으로 돌아오자.
- 회원 목록 화면에서 등록 버튼을 추가하고 등록 화면을 호출하자.
- 사용자 정보를 입력받고 회원 등록 Servlet을 호출하자.
- 회원 등록 Servlet에서 Transaction을 알아보자.
- 회원이 등록되면 회원 목록 화면으로 보내자.
2. 회원 목록 버튼 추가
내용이 조금 늘었으니 변경된 부분만 보자.
소스코드 :
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<script src="https://code.jquery.com/jquery-3.5.0.js"></script>
<body>
<form id="mberListFrm" name="mberListFrm" method="post">
<div align="right" style="width: 90%">
<a href="javascript:void(0);" id="btnMberRegistView" style="text-decoration:none; border:1px solid; background-color: lightgreen; width: 3em">등록</a>
</div>
<br/>
<table style="border:1px solid blue; width: 90%;">
<tr>
...
</tr>
</table>
</form>
</body>
<script type="text/javascript">
$(document).ready(function(){
// 등록 화면으로 이동
$("#btnMberRegistView").click(function() {
location.href = "/mberRegistView.jsp";
});
...
});
</script>
회원 등록 화면을 호출 시 별다른 Parameter를 보낼 게 없으니. jsp 바로 호출하자. 간단한 화면 이동에서는 Submit 하지 않고 location.href = "" 사용하는데 이는 새 화면을 호출하는 Script 명령어다. history가 쌓이고 어쩌고 내용이 있긴 한데 늘 그렇듯 이 녀석이 화면 이동시켜준데! 만 생각하고 그냥 쓰자. (history back을 신경 써야 할 때 찾아보면 될 것 같다.)
3. 회원 등록 화면 (mberRegistView.jsp)
JSP 개발에서 만들어둔 거 가져와서 복붙 했다. (역시 개발은 복붙이 진리인듯? ㅎㅎ)
소스코드 :
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<script src="https://code.jquery.com/jquery-3.5.0.js"></script>
<body>
<form id="registFrm">
<table style="border:1px solid blue;">
<tr>
<td>회원 아이디</td>
<td><input type="text" id="mberId" name="mberId"></td>
<td>회원 비밀번호</td>
<td><input type="text" id="mberPwd" name="mberPwd"></td>
</tr>
<tr>
<td>회원 이름</td>
<td><input type="text" id="mberNm" name="mberNm"></td>
<td>회원 휴대폰</td>
<td><input type="text" id="mberMoblphon" name="mberMoblphon"></td>
</tr>
<tr>
<td>비고</td>
<td colspan="3"><input type="text" id="rm" name="rm" style="width: 100%"></td>
</tr>
<tr>
<td colspan="4">
<div align="right">
<a href="javascript:void(0);" id="btnMberRegist" style="text-decoration:none; border:1px solid; background-color: lightgreen;">저장</a>
<a href="javascript:void(0);" id="btnMberListView" style="text-decoration:none; border:1px solid; background-color: lightgreen;">목록으로</a>
</div>
</td>
</tr>
</table>
</form>
</body>
<script type="text/javascript">
var isRegistCnt = "${registResult}";
$(document).ready(function(){
// 등록
$("#btnMberRegist").click(function() {
var frm = $("#registFrm");
frm.attr("method", "post");
frm.attr("action", "/mberRegist.do");
frm.submit();
});
// 회원 목록으로
$("#btnMberListView").click(function() {
var frm = $("#registFrm");
frm.attr("method", "post");
frm.attr("action", "/mberList.do");
frm.submit();
});
if (isRegistCnt != "" && isRegistCnt != null && isRegistCnt != undefined) {
if (isRegistCnt > 0) {
alert("회원 등록이 완료되었습니다.");
$("#btnMberListView").trigger("click");
} else {
alert("회원 등록을 실패했습니다.");
}
}
});
</script>
이전 소스코드와 크게 다르지 않지만 굳이 찾아보면 jquery를 넣어주고 javascript 변수에 el 값을 할당해준 것인데 $(document).ready().. 아래를 보면 el에서 받은 값이 있냐? 없냐를 따져 묻고 데이터가 있는데 0보다 큰 값이라면 '회원 등록이 완료되었습니다.'를 알림 처리를 한 후 회원 목록으로 이동하게 했다. el 값을 활용한 것을 보면 이는 Servlet에서 SQL 수행 후 현재 화면으로 다시 돌아오겠다는 것이고 돌아오는 데이터를 받아 후처리를 하겠다는 걸로 생각하자. 등록 완료 시 수행되는 내용 중 $("#..").trigger("click"); 라는 함수는 클릭하지 않아도 클릭한 것과 같은 효과를 주는 강제 이벤트 발생 함수이고 이 강제 이벤트 발생으로 목록으로 이동하게 된다. jquery는 아~ 이런것도 되는구나 정도로만 참고하자. 그리고 저장 외에도 목록으로 이동할 수 있도록 버튼을 추가해준 것인데 등록 화면으로 올 때 와는 다르게 목록은 Submit을 사용했다 왜일까? 목록은 데이터를 출력해야는데. jsp를 호출하면 데이터가 없지 않은가? 그래서 Servlet을 호출하여 조회 SQL을 수행하고 데이터를 설정 후 Dispatcher forward로 회원 목록이 호출되어야 정상적으로 보이게 된다. 잊지 말자 데이터 전달은 곧 죽어도 forward다 물론 get방식으로 보내고 받을 수도 도 있지만 post로만 처리할 생각이라 get으로 받을 일 없음. (설마 get을 쓰게... 되면 어쩌지?;;;)
- javascript el 값 할당
jsp는 컴파일시 우선 순위를 가지는데 이게 무슨 말이냐면 jsp 표현법으로 스크립트릿, jstl, el, html tag, javascript... 등등 이것들을 순서 없이 컴파일하면 중구난방 되지 않을까? 그래서 스크립트릿을 최우선으로 java와 가까운 애들이 먼저 컴파일 된다. 그래서 el이 먼저 해석되어 이것이 무엇을 의미하는지 이미 알고 뒤에 해석되는 javascript에 값을 할당 할 수 있게된다. 그럼 반대로는 될까? 안된다. 그냥 안되니깐 고민말고 쓰도록 하자.
- trigger
함수 설명은 설명했으니 넘어가고 이 함수의 사용 위치를 보면 이벤트 가장 하단에 위치하고 있는데 위치가 아랫쪽인 이유가 소스코드는 위에서 아래로 읽혀져 내려가기 때문에 $("#btnMberListView").click(... 이벤트 보다 윗쪽으로 코딩하면 강제 이벤트 발생 함수인 trigger는 자기보다 뒤에 있는 대상 이벤트를 찾지를 못한다. 즉 btnMberListView tag에 이미 설정된 이벤트를 강제로 실행 하는 것이지 동적으로 생성하고 이벤트 발생 시키는 것은 아니다. 동적 이벤트는 나중에 또 알아보자.
4. 회원 등록 Servlet (MberRegistServlet.java)
등록 화면과 마찬가지로 SQL부분만 뗘서 복붙 했다. ㅎㅎ
소스코드 :
package com;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MberRegistServlet extends HttpServlet {
private static final long serialVersionUID = 3161530544990290786L;
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// get 방식으로 안보낼 생각임
}
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
Connection dbConn = null;
int resultNum = 0;
try {
String paramMberId = req.getParameter("mberId");
String paramMberPwd = req.getParameter("mberPwd");
String paramMberNm = req.getParameter("mberNm");
String paramMberMp = req.getParameter("mberMoblphon");
String paramRm = req.getParameter("rm");
System.out.println("paramMberId : " + paramMberId);
System.out.println("paramMberPwd : " + paramMberPwd);
System.out.println("paramMberNm : " + paramMberNm);
System.out.println("paramMberMp : " + paramMberMp);
System.out.println("paramRm : " + paramRm);
Class.forName("org.mariadb.jdbc.Driver");
dbConn = DriverManager.getConnection(
"jdbc:mariadb://127.0.0.1:3306/oldev"
, "olDev"
, "olDev@1234"
);
Statement stmt = dbConn.createStatement();
String sqlStr = "";
sqlStr += "INSERT INTO OD_MBER ";
sqlStr += "( ";
sqlStr += " MBER_ID ";
sqlStr += ", MBER_PWD ";
sqlStr += ", MBER_NM ";
sqlStr += ", MBER_MOBLPHON ";
sqlStr += ", RM ";
sqlStr += ", REGIST_SN ";
sqlStr += ", REGT_DTTM ";
sqlStr += ", UPDT_SN ";
sqlStr += ", UPDT_DTTM ";
sqlStr += ") ";
sqlStr += "VALUES ";
sqlStr += "( ";
sqlStr += " NULLIF('"+paramMberId+"', '') ";
sqlStr += ", NULLIF('"+paramMberPwd+"', '') ";
sqlStr += ", NULLIF('"+paramMberNm+"', '') ";
sqlStr += ", NULLIF('"+paramMberMp+"', '') ";
sqlStr += ", NULLIF('"+paramRm+"', '') ";
sqlStr += ", '0' ";
sqlStr += ", DATE_FORMAT(NOW(), '%Y%m%d%H%i%s') ";
sqlStr += ", '0' ";
sqlStr += ", DATE_FORMAT(NOW(), '%Y%m%d%H%i%s') ";
sqlStr += ") ";
resultNum = stmt.executeUpdate(sqlStr, 1);
ResultSet resultSet = stmt.getGeneratedKeys();
String genKey = null;
if (resultNum > 0) {
while(resultSet.next()) {
genKey = resultSet.getString(1);
}
}
if (!"".equals(genKey) && genKey != null) {
String sqlStr2 = "";
sqlStr2 += "UPDATE OD_MBER ";
sqlStr2 += " SET REGIST_SN = '"+genKey+"' ";
sqlStr2 += " , UPDT_SN = '"+genKey+"' ";
sqlStr2 += " WHERE MBER_SN = '"+genKey+"' ";
resultNum += stmt.executeUpdate(sqlStr2);
}
} catch (SQLException e) {
resultNum = 0;
e.printStackTrace();
} catch (ClassNotFoundException e) {
resultNum = 0;
e.printStackTrace();
}
req.setAttribute("registResult", resultNum);
RequestDispatcher rd = req.getRequestDispatcher("/mberRegistView.jsp");
rd.forward(req, resp);
}
}
뭐 특별한 건 없고 소스코드를 보면 Reuqest Parameter로 화면에서 보내오는 데이터를 받아 Insert SQL을 수행하고 Auto_Increment 님을 꺼내다가 update 해주는 그대로를 사용하고 다시 등록 화면으로 forward 처리해주어 화면에서 등록 여부에 따른 후처리를 할 수 있도록 해 준 게 전부다.
뭐 특별한 건 없으니깐 실행을 한 번 시켜보자.

등록 화면으로 들어와 아이디를 test 10으로 입력하고 등록해보았다. 별 뭐 특별한 이유가 없으니 잘 등록된다.
딱히 발생할 오류가 없으므로 소스코드에 강제로 Exception을 추가하고 한 번 더 테스트해보자.
소스코드 :
package com;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MberRegistServlet extends HttpServlet {
private static final long serialVersionUID = 3161530544990290786L;
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// get 방식으로 안보낼 생각임
}
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
Connection dbConn = null;
int resultNum = 0;
try {
...
// 강제로 Exception
throw new Exception("Transaction Test!");
} catch (SQLException e) {
resultNum = 0;
e.printStackTrace();
} catch (ClassNotFoundException e) {
resultNum = 0;
e.printStackTrace();
// catch 추가
} catch (Exception e) {
resultNum = 0;
e.printStackTrace();
}
req.setAttribute("registResult", resultNum);
RequestDispatcher rd = req.getRequestDispatcher("/mberRegistView.jsp");
rd.forward(req, resp);
}
}
Insert, Update SQL을 수행하고 Exception을 강제로 발생시켰다. 예외가 발생하면 데이터가 등록이 되지 않기를 바래서 강제로 Exception을 발생시켜 보았다. 어떻게 되는지 살펴보자.

아이디, 이름, 비고를 test11로, 비밀번호 1234인 데이터를 저장시켜보면 Insert, Update SQL 수행 후 Exception을 throw 하도록 했으니 이미지와 같이 eclipse console에 Exception Message로 설정한 Transaction Test! 와 화면에서 registResult는 비어있지 않고 결과 값은 오류였으므로 알림을 실패로 노출하고 있다. 그렇다면 목록에서 과연 강제로 Exception을 발생시켜 안 들어가길 바랬는데 정말 안 들어갔는지 확인해보자.

안타깝게도 데이터는 들어가 있다. 왜 들어갔을까? 테스트를 한 번 더 해보자. 이미 들어갔으니 똑같이 test11로 설정하고 저장해보자.

같은 과정의 반복이므로 다른 점만 살펴보면 앞서 했던 저장은 Transaction Test! Message가 출력 됐는데 이번엔 좀 다른 Exception Message 발생했다. 이는 OD_MBER 테이블을 생성할 때 MBER_ID에 제약조건으로 UNIQUE 제약을 주었기 때문에 중복된 아이디인 test11 값이 Insert 될 수 없어 DB가 SQLException을 발생시켰다. 다시 목록으로 가보자.

목록을 다시 조회해보면 이번엔 test11이 들어가지 않았다. 앞서 throw Exception이 던져졌을 땐 데이터가 들어갔는데 SQLExcpetion 발생했을 땐 들어가지 않는다. 왜일까? SQLException과 Exception 둘을 놓고 차이를 생각해봐야 답이 안 나온다. SQLException은 우리가 java로 코딩을 할 때 문법에 오류가 발생해서 컴파일 안되것이고 이와 같은 개념으로 DB입장에서 등록하라고 받은 데이터 자체가 문제여서 java처럼 컴파일이 안되니 나 이거 못해먹겠어! 하고 보내온 것이 SQLException이다. 이것과는 다르게 Insert, Update 후에 Exception을 던졌을 땐 DB입장은 어 그래 이거 문제없는 데이터네 받아줄께 하고 처리를 해주었던 것이고 그런 DB의 입장과는 다르게 Exception을 발생시켜 등록을 막아보려 했을 뿐이다. 그렇다면 지금과 같이 Insert 하고 후처리 로직에서 Error가 발생하면 후처리를 무시하고 Insert를 유지할 것인가? 물론 그런 비즈니스도 있겠지만 보통은 후처리를 포함하여 데이터의 정합성을 유지해야 하므로 이와 같은 일이 발생될 때 제어하기 위해 Transaction을 알아보자.
5. DB Transaction
반복적으로 하는 말이지만 간단하게 맛만 보고 넘어가자 요고 하나만으로 책 한 권 나오는 내용이다. 그래서 UNDO, REDO, 무정지성, Connection 통신 뭐 등등 어려운건 접어두고 Commit과 Rollback만 알아보자.
Transation은 한마디로 정의하자면 하나 또는 둘 이상의 처리를 하나의 흐름으로 관리하고 결과 또는 필요에 따라 기록(Commit)과 원복(Rollback)하는 개념으로 생각하면 될 것 같은데 밑에 그림을 하나 보자.

그림을 보면 소스코드에는 없는데 Trasaction 부분은 어디서 선언했지?라고 생각할 수 있지만 Connection 받아오면 Transaction은 물려 있다고 생각하면 된다. 왜 그런가 하면 Connection 객체를 받으면 Trasaction이 걸려 있고 이를 껐다 켰다 하는 것이지 new Transction()이나 Transaction.getInstance() 따위를 하는 것은 아니다. 깊이 있게 까고 들어가면 다르겠지만 Connection 객체로 껐다 켰다 하는 영역이므로 물고 온다고 생각해도 될 것 같다. 여기서 껐다 켰다는 진짜 끄고 키는 게 아니라 그렇다는 의미이다. 뭐 쨌든 흐름이나 한번 보자 Connection Open, Transaction 설정, Statement SQL을 수행하는 흐름이고 Statement가 영향을 받는다고 표기해뒀는데 영향을 받는다는 의미가 데이터의 등록, 수정, 삭제에 대한 질의는 Statement로 수행하고 질의에 대한 결과는 commit(기록) 또는 rollback(원복)으로 완료를 해야 한다는 거다. 이는 기껏 데이터 넣었는데 Rollback 하면 원복 되어 없지는 것이고 Error 났는데 Commit 하면 부정합 한 데이터가 기록 될 수 있게 되므로 해당 질의가 영향을 받았다 표현한 것이다.
그리고 저렇게 Statement를 싸고 있는 Transaction은 기본적으로 AutoCommit으로 설정되어 있는데 이를 Auto 즉 자동으로 사용하지 않고 원하는 시점에서 사용하고 싶으면 AutoCommit을 False로 설정해야 한다. AutoCommit을 False로 사용하면 등록, 수정, 삭제 질의를 수행 후 Commit 또는 Rollback을 직접적으로 소스코드에 기술해야 하고 이를 까먹고 기술하지 않으면 문제가 발생하는데 그 문제가 기껏 데이터 넣었는데 다른 Transaction은 내가 넣어둔 데이터를 확인할 수가 없다. 물론 Rollback 하면 못 보는 건 똑같은데 그 의미가 아니라 하나의 Transaction은 Commit, Rollback을 만나기 전까지는 현재 수행되는 곳에서만 알고 있는 정보라는 것이고 회원을 등록했는데 회원 목록에서는 볼 수가 없다는 이야기이다. 그렇기 때문에 AutoCommit을 False로 사용하면 반드시 소스코드 끝에는 Commit 또는 Rollback을 해주도록 하자. 이는 Transction의 개념 중 독립성과 격리성에 의한 것인데 뭐... 그렇다고 하던데... 쩝... 넘어가고..
그래서 앞서 테스트해본 소스코드는 AutoCommit 설정을 기본으로 사용했기 때문에 Exception이 발생해도 Insert 된 데이터가 Commit 되어 목록으로 노출되게 된 것이다. 그렇다면 insert 또는 update된 데이터의 후처리의 영향으로 원복해야 한다면 AutoCommit False 설정해서 내가 원하는 Rollback을 할 수 있지 않을까? 당연히 되고 그렇게 해야된다. 그래서 AutoCommit을 False로 설정하고 테스트를 해보자.
HedSql DB 툴을 열어 아래 SQL을 실행시켜보자.
show variables like 'autocommit%';

이미지와 같이 Value 값이 ON이면 AutoCommit이 true이므로 꺼주자.
SET AUTOCOMMIT = TRUE; -- 설정
SET AUTOCOMMIT = FALSE; -- 해제
우리는 해제하고 Commit, Rollback을 테스트해볼 테니 SET AUTOCOMMIT = FALSE; 를 입력하자.
이는 현재 Open 상태일 때만 적용되는 내용이니 항상 꺼두고 싶다면 구글님께 문의하자..;;
설정을 실행하고 다시 조회해보면 OFF로 설정되었을 것이고 DB툴을 하나 더 열어보자.

DB툴을 이렇게 두 개를 열었다면 아래 Insert SQL을 복붙 해서 실행해보자.
INSERT INTO OD_MBER
(
MBER_ID
, MBER_PWD
, MBER_NM
, MBER_MOBLPHON
, RM
, REGIST_SN
, REGT_DTTM
, UPDT_SN
, UPDT_DTTM
)
VALUES
(
'test99'
, '1234'
, '홍길동'
, '01012345678'
, NULL
, '1'
, DATE_FORMAT(NOW(), '%Y%m%d%H%i%s')
, '1'
, DATE_FORMAT(NOW(), '%Y%m%d%H%i%s')
);
Insert를 수행했다면 DB툴 두 곳에서 조회를 하자.

이미지와 같이 좌측 AutoCommit False를 설정하고 insert를 수행하면 Commit을 수행하지 않았기 때문에 우측 DB툴에서는 조회가 되지 않는다. Commit을 수행하고 다시 조회를 해보자.
COMMIT;

좌측 DB툴에서 Commit을 수행하고 조회를 하면 우측에서도 보이는 것을 알 수 있다. 즉 Commit(기록) 하라고 알려 주어야 다른 쪽에서 해당 내용을 확인할 수 있게 되는 것이다.
Rollback은 다른 쪽에서는 어차피 모르는 것이고 현재 내가 작업하 것을 원복 즉 되돌리고 싶을때 사용하면 된다. 위 이미지에서 Rollback을 좌측 DB툴에서 실행하고 Select하면 test99번이 사라지게 된다.
Rollback은 별도로 캡쳐나 소스코드를 올리진 않을텐데 테스트를 해보고 싶다면 아래와 같이 하면 된다.
* Insert SQL에서 test99번 값을 test100으로 수정하고 수행 후 Select 해보면 잘 보이다가 Rollback을 수행하면 없어지는 것을 확인할 수 있다. 똑같이 Insert를 한번더 수행하면 또 test100이 들어간다. MBER_ID는 UNIQUE 제약조건이 걸려있기 때문에 만약 Rollback으로 원복되지 않았다면 DB툴에서 error message를 보았을 것이다.
근데 위 그림대로면 java로 작업해서 소스코드로 올려야 하는거 아닌가? Servlet으로 Request 들어오고 Connection 객체 받아오고 하는거 다 어디가고 갑자기 DB툴로 테스트하나? 할 수도 있는데 DB툴 좌측 상단 메뉴 중 파일을 선택하면 첫 번째 하위 메뉴로 세션 관리자 메뉴가 있다 클릭해보자.

이미지를 보면 DriverManager.getConnection(....) 설정과 별 차이 없지 않나? 똑같이 Connection 받아다 쓰는 거는 마찬가지다. 그래서 쉽게 테스트하기 위해서 DB툴을 사용한 것일 뿐....인데... 뭐 쨌든 또 넘어가고 ㅎ
이렇게 간단하게 Transaction을 알아보았고 그래서 소스코드를 어떻게 고치라는 건지 소스코드나 수정해보자.
6. 회원 등록 Servlet Transaction 설정 변경
이미 위에서 한번 훑어본 소스코드니 변경점만 간단히 보도록 하자.
소스코드 :
package com;
import ...
public class MberRegistServlet extends HttpServlet {
private static final long serialVersionUID = 3161530544990290786L;
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// get 방식으로 안보낼 생각임
}
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
Connection dbConn = null;
int resultNum = 0;
try {
...
Class.forName("org.mariadb.jdbc.Driver");
dbConn = DriverManager.getConnection(
"jdbc:mariadb://127.0.0.1:3306/oldev"
, "olDev"
, "olDev@1234"
);
dbConn.setAutoCommit(false);
....
dbConn.commit();
} catch (Exception e) {
resultNum = 0;
e.printStackTrace();
try {
if (dbConn != null) {
dbConn.rollback();
}
} catch (SQLException e1) {
e1.printStackTrace();
}
}
req.setAttribute("registResult", resultNum);
RequestDispatcher rd = req.getRequestDispatcher("/mberRegistView.jsp");
rd.forward(req, resp);
}
}
Connection의 method로 setAutoCommit을 제공하는데 이 AutoCommit이 Transaction을 원하는 시점에 사용 할 수 있도록 설정하는 것이다. 앞서 이야기 한대로 false로 설정 했기 때문에 SQL 수행 후 내용이 끝나기전 commit()을 수행했고 예외 상황이 발생하면 try catch에서 rollback()을 수행한다. 보편적으로 오류 상황일때 원복을 해야하므로 catch에서 수행하지만 필요 하다면 분기문에서 처리할 수도 있다. rollback() method는 SQL throws 하고 있기 때문에 한번더 try catch 해주었다. (catch에 Exception 유형별로 처리하기 귀찮아서 Exception 처리해버림 ㅎㅎ)
7. web.xml
MberRegistServlet이 추가되었으니 아래와 같이 Servlet mapping을 설정하자.
소스코드 :
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID"
version="2.5">
...
<servlet>
<servlet-name>mberRegist</servlet-name>
<servlet-class>com.MberRegistServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>mberRegist</servlet-name>
<url-pattern>/mberRegist.do</url-pattern>
</servlet-mapping>
</web-app>
설정안하면 Serlvet을 찾지 못해 오류 화면을 보게 된다. 꼭 설정 해주자.
이렇게 목표대로 등록하고 Transaction도 간략하지만 알아보았으니 여기서 끝!
다음은 수정, 삭제를 만들어 보자.... 점점 글이 많아지네 하....
'JAVA_Servlet' 카테고리의 다른 글
| 초보의 Servlet 개발 수정, 삭제 그리고 Connection (0) | 2020.11.25 |
|---|---|
| 초보의 Servlet 개발 jstl, el 그리고 jquery (0) | 2020.11.23 |
| 초보의 Servlet 개발 조회 (0) | 2020.11.20 |
| 초보의 Servlet 개발 화면이동 (0) | 2020.11.19 |
| 초보의 Servlet 개발 Request, Response (0) | 2020.11.18 |
댓글