본문 바로가기
DB/Code

CODE [day_05] DB / 08_2. Transaction (COMMIT, ROLLBACK) 적용한 예제 - 신용카드 발급 시에 포인트를 지급하기

by 파프리카_ 2020. 8. 12.
728x90
반응형

트랜잭션 처리를 통해, 발생될 수 있는 문제를 해결한 예제

 

*SQL TABLE의 정보들은 모두 지워주고, 기존 테이블 틀만 재활용한다.

JAVA JDBC

 

TestDAO class (main class)

 

트랜잭션 처리를 통해 모든 작업이 정상적으로 수행되었을 때 COMMIT,

문제 발생 시 ROLLBACK 처리를 한 예제

 

Test 1 : 정상적인 데이터를 입력해 commit 확인

Test 2 : point 등록 시 고의로 오류를 발생시켜 rollback이 되는지 확인

 

/TestTransaction2.java

package test;

import model.CardDAO2;


public class TestTransaction2 {
	public static void main(String[] args) {
		try {
			CardDAO2 dao = new CardDAO2();
			
			dao.registerCardAndPoint("java2", "복숭아", "롯데", 1000);
			System.out.println("카드 발급이 정상적으로 처리되었습니다.");
            
		} catch (Exception e) {
			System.out.println("카드 발급과정에서 오류가 발생하여 카드 발급이 취소되었습니다.");
		}
	}
}

 

> CONSOLE 결과

Test 1

Test 2

 

> SQL DB 결과

Test 1 

[ Card TABLE ]

[ Point TABLE ]

 

Test 2 

[ Card TABLE ]

[ Point TABLE ]

 


DAO ( Data Access Object ) class

 

CardDAO 에서는 카드가 등록되고,

포인트 등록 시 에러가 발생하더라도 카드는 실제 DB에 정보가 등록되는 논리상 문제가 발생했다.

(링크: https://creamilk88.tistory.com/67 )

 

트랜잭션 처리를 통해 하나의 작업 단위 (카드 등록과 포인트 등록)가 모두 문제없이 잘 수행되었을 때에만,

실제 데이터베이스에 등록되도록(COMMIT) 처리를 해본다.

문제 발생 시에는 모든 작업이 취소되도록(ROLLBACK) 처리한다. 

 

/CardDAO2.java

package model;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import common.DbInfo;

public class CardDAO2 {
	
	//생성자
	public CardDAO2() throws ClassNotFoundException {
		Class.forName(DbInfo.DRIVER_NAME);
	}
	
	//closeAll
	public void closeAll(PreparedStatement pstmt, Connection con) throws SQLException {
		if (pstmt != null)
			pstmt.close();
		if (con != null)
			con.close();
	}

	//registerCardAndPoint method
	public void registerCardAndPoint(String id, String name, String point_type, int point) throws SQLException {
		Connection con = null;
		PreparedStatement pstmt = null;
		try {
			con = DriverManager.getConnection(DbInfo.URL, DbInfo.USER, DbInfo.PASS);
			
			//트랜잭션 처리를 위해 오토커밋 모드를 해제한다.
	        con.setAutoCommit(false);

			// 1. card table에 insert
			String insertCardSql = "INSERT INTO card(id, name) "+
									"VALUES(?, ?)";

			pstmt = con.prepareStatement(insertCardSql);
			pstmt.setString(1, id);
			pstmt.setString(2, name);
			int resultCard = pstmt.executeUpdate();
			System.out.println("CARD INSERT SUCCESS --> " + resultCard);
			pstmt.close();		
					
			// 2. point table에 insert
			String insertPointSql = "INSERT INTO point(id, point_type, point) "+
									"VALUES(?, ?, ?)";
			pstmt = con.prepareStatement(insertPointSql);
			pstmt.setString(1, id);
			pstmt.setString(2, point_type);
			pstmt.setInt(3, point);
			int resultPoint = pstmt.executeUpdate();
			System.out.println("POINT INSERT SUCCESS --> " + resultPoint);

			// 카드 발급 작업이 모두 정상적으로 수행되었을 때,
			// 실제 데이터베이스에 정보를 등록
			con.commit();
			System.out.println("카드 발급의 모든 작업이 정상적으로 수행되어 COMMIT 합니다!");

		} 
		
		catch (Exception e) 
		{
			con.rollback();
			System.out.println("카드 발급 작업 시 문제가 발생되어 작업을 취소하고 되돌립니다. ROLLBACK ! ");
			//사용자 코드(client code)측에 예외 상황을 알리기 위해,
			//다시 예외를 발생시켜 호출한 곳으로 전달하기 위해 아래 코드를 작성한다.
			throw e;
		}
		
		finally 
		{
			closeAll(pstmt, con);
		}
	}
}
728x90
반응형