프로그래밍/JDBC

jdbc에서 트랜잭션 처리하기 예제

Jay Tech 2017. 1. 13. 16:28
반응형

두 쿼리가 실행되어야 하는 상황이 있다.

첫 번째 쿼리는 됐지만 두 번째 쿼리에서 문제가 발생하였다.

그렇다면 데이터가 잘못된 상태로 저장이 된 것이다.


두 쿼리가 모두 정상적으로 실행되어야 데이터의 무결성이 유지되기 때문이다. 그래서 한 개이상의 쿼리가 모두 성공적으로 실행되어야 데이터가 정상적으로 처리되는 경우 DBMS 트랜잭션(transaction)을 이용해서 한 개 이상의 쿼리를 마치 한개의 쿼리 처럼 처리할 수 있다.


트랜잭션은 시자고가 종료를 갖고 있다. 트랜잭션이 시작되면 이후로 실행되는 쿼리 결과는 DBMS에 곧바로 반영되지 않고 임시로 보관된다. 이후 트랜잭션을 커밋하면 임시로 보관된 모든 쿼리 결과가 실제 데이터에 반영된다. 


1. 트랜잭션 시작 : 트랜잭션 시작 이후 실행되는 쿼리를 하나의 작업으로 처리한다.


쿼리1, 쿼리2, 쿼리3..........


2. 트랜잭션 커밋 : 트랜잭션 시작 후 에러가 발생되지 않으면 쿼리 결과를 DB에 반영한다.


3. 트랜잭션 롤백 : 에러가 발생하면 실행된 쿼리 결과를 DB에 반영하지 않고 취소함.



JDBC API를 이용해서 한 개 이상의 쿼리를 트랜잭션으로 묶어서 처리하고 싶다면 쿼리를 실행하기 전에 Connection.setAutoCommit()을 false로 주어야 한다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import = "java.sql.DriverManager" %>
<%@ page import = "java.sql.Connection" %>
<%@ page import = "java.sql.PreparedStatement" %>
<%@ page import = "java.sql.SQLException" %>
<%
    String idValue = request.getParameter("id");
    
    Connection conn = null;
    PreparedStatement pstmtItem = null;
    PreparedStatement pstmtDetail = null;
 
    String jdbcDriver = "jdbc:mysql://localhost:3306/chap12?" +
                        "useUnicode=true&characterEncoding=euckr";
    String dbUser = "id";
    String dbPass = "pw";
    
    Throwable occuredException = null;
    
    try {
        int id = Integer.parseInt(idValue);
        
        conn = DriverManager.getConnection(jdbcDriver, dbUser, dbPass);
        conn.setAutoCommit(false);
        
        pstmtItem = conn.prepareStatement("insert into ITEM values (?, ?)");
        pstmtItem.setInt(1, id);
        pstmtItem.setString(2"상품 이름 " + id);
        pstmtItem.executeUpdate();
        
        if (request.getParameter("error"!= null) {
            throw new Exception("의도적 익셉션 발생");
        }
        
        pstmtDetail = conn.prepareStatement(
            "insert into ITEM_DETAIL values (?, ?)");
        pstmtDetail.setInt(1, id);
        pstmtDetail.setString(2"상세 설명 " + id);
        pstmtDetail.executeUpdate();
        
        conn.commit();
    } catch(Throwable e) {
        if (conn != null) {
            try {
                conn.rollback();
            } catch(SQLException ex) {}
        }
        occuredException = e;
    } finally {
        if (pstmtItem != null)
            try { pstmtItem.close(); } catch(SQLException ex) {}
        if (pstmtDetail != null)
            try { pstmtDetail.close(); } catch(SQLException ex) {}
        if (conn != nulltry { conn.close(); } catch(SQLException ex) {}
    }
%>
<html>
<head><title>ITEM 값 입력</title></head>
<body>
 
<%  if (occuredException != null) { %>
에러가 발생하였음: <%= occuredException.getMessage() %>
<%  } else { %>
데이터가 성공적으로 들어감
<%  } %>
</body>
</html>
 
cs



line 24 트랜잭션을 시작한다.


그리고 여러 쿼리를 작성해주고 line 41에서 트랜잭션을 커밋한다.


예외가 터진다면 line 45에서 롤백을 해준다.



반응형