1. ResultSetMetaData 

- data dictionary를 사용하지 않고, 실행되는 select 쿼리에 해당하는 컬럼정보를 얻을 때 사용하는 ineterface

- 조회된 inline view에 한하여 컬럼정보 조회 가능

- DBMS가 달라도 정보를 얻을 수 있음

   > Oracle의 user_cons_columns ,,, 등과 같은 다양한 data dictionary는 oracle DB에서만 존재/사용 가능

- ResultSet을 기반으로 생성되며, ResultSet은 연결 끊어야 하나 ResultSetMetadata는 연결 안 끊어도 됨

- 사용법) 

> ResultSet에서 ResultSetMetaData를 얻기 : ResultSetMetaData rsmd = getMetaData();

> 정보 얻기

  • 컬럼의 개수 : rsmd.getColumnCount()
  • 컬럼명 : rsmd.getColumnName(컬럼 인덱스) or getColumnLabel (oracle의 컬럼 index는 1부터 시작)
  • 컬럼 데이터형명 : rsmd.getColumnTypeName(컬럼의 인덱스)
  • 컬럼 데이터형크기 : rsmd.getPrecision(컬럼의 인덱스)
  • null 허용 : rsmd.isnullable(컬럼의 인덱스) // not null이면 0 null 허용이면 1

 

 

 2. Transaction 처리 

- 데이터베이스의 작업 단위 (insert, update, delete)

- 작업이 완료될 때 commit, 작업을 취소할 때 rollback 사용 

- java에서는 Connection Interface가 Transaction을 처리

    > Transaction 대상쿼리문 하나 당 작업완료 (auto commit)

- auto commit 문제 : 

    > Transaction 대상 쿼리문 하나로 작업이 완료되면 auto commit은 문제를 발생시키지 않지만,

       여러 개의 쿼리문이 하나의 Transaction을 구성하면 문제를 발생시킬 수 있음

    > 여러 개의 작업이 모두 성공했을 때에만 DB작업이 완료되어야 하고,

       여러 개의 작업 중 하나라도 실패하면 모든 DB작업이 취소되어야 함 

    > 여러 쿼리가 있을 때 Transaction으로 관리하자

- 작업방법)

1) Connection의 auto commit을 해제

     con.setAutoCommit(false) ;  // 개발자가 transaction 완료 후 commit 또는 rollback 해야 함

    *주의 : method 안에서 Connection을 종료하면 commit이 된 후 Connection이 종료되므로,

                 연결 끊기는 DB작업 method 밖에서 끊음 

     (Connection을 DB작업 method 외부에서 선언 <- method가 2개로 분리됨)

2) 쿼리문 작업 외부에 Connection 선언 

3) DB작업 method가 쿼리 수행 행수를 반환

4) DB작업 method가 개발자가 목표로 한 레코드 수를 반환했을 때에만 commit 또는 rollback을 수행하고 연결을 끊음

 

- rollback 처리시 차이점:

1) update/delete의 경우 : 쿼리문 수행 실패 시 0건 수행이므로 else 부분에서 rollback 처리

2) insert의 경우 : 쿼리문 수행 실패 시 SQLException 발생하므로 catch 부분에서 rollback 처리

 

 


# 오늘의 코딩 #

- Transaction을 처리해보자

- 여러 쿼리문을 실행하고 모두 수행되었을 경우에만 commit!

 

# DB 구성은 아래와 같다!

- TRANSACTION2 테이블의 주소컬럼의 크기를 작게 설정하여 INSERT 되지 않을 경우/될 경우를 TEST 예정

TRANSACTION1
TRANSACTION2

 

# Transaction Test할 클래스

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

import test.dao.DbConnection;

/**
 * 쿼리문 여러개로 하나의 Transaction이 구성되는 경우의 처리
 * @author user
 */
 
public class TestTransaction {

	/**
	 * transaction을 처리할 쿼리문을 실행하고, 결과를 받아와서 transaction을 완료하는 method
	 */
	@SuppressWarnings("resource")
	public void transaction() {
		Connection con = null;
		try {
			// 2. 커넥션 얻기
			con = DbConnection.getInstance().getConn();
			// autocommit 해제
			con.setAutoCommit(false);
			// 3. 쿼리문 수행 후 결과 얻기
			int cnt = sqlJob(con); // 여러개의 쿼리문이 하나의 transaction을 구성
			// 쿼리문이 실행된 후 목표로 한 행수가 나오면 commit 아니면 rollback
			if (cnt == 2) {
				con.commit(); }// 트랜잭션 완료
		} catch (SQLException e) {
			try {
				 // insert로 트랜잭션이 구성되는 경우 catch 에서 rollback을 처리함
				con.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}//end catch
			e.printStackTrace();
		} finally {
			try {
				if (con != null) {
					con.close();
				} // end if
			} catch (SQLException e) {
				e.printStackTrace();
			} // end catch
		} // end finally
	}// transaction

	/**
	 * Connection을 받아, DB작업을 수행하는 method<br>
	 * transaction1 테이블과 transaction2 테이블에 이름과 주소를 입력하여 추가된 행수를 반환하는 일
	 * 
	 * @param con
	 * @return 쿼리문을 수행한 결과 횟수 (총합)
	 * @throws SQLException
	 */
	public int sqlJob(Connection con) throws SQLException {
		int allCnt = 0;  // 쿼리문 수행 성공 횟수를 담을 변수

		String name = "김동동";
		String addr = "서울시 동작구";

		// 쿼리문 수행객체 얻기
		// transaction1 테이블에 작업
		String insert1 = "insert into transaction1(name,addr) values (?,?)";
		PreparedStatement pstmt = con.prepareStatement(insert1);
		pstmt.setString(1, name);
		pstmt.setString(2, addr);

		int cnt1 = pstmt.executeUpdate();

		// transaction2 테이블에 작업
		String insert2 = "insert into transaction2(name,addr) values (?,?)";
		PreparedStatement pstmt2 = con.prepareStatement(insert2);
		pstmt2.setString(1, name);
		pstmt2.setString(2, addr);

		int cnt2 = pstmt2.executeUpdate();

		allCnt = cnt1 + cnt2;

		return allCnt;
	}// sqlJob

	public static void main(String[] args) {
		TestTransaction tt = new TestTransaction();
		tt.transaction();
	}// main

}// class

 

# 출력 결과 #

1) INSERT 정상 처리 (이름 : 김동동 / 주소 : 서울)

- 두 테이블 모두 정상 적으로 INSERT 처리되어 커밋 됨!

2) 오류 발생 시 에러 메시지(이름 : 김동동 / 주소 : 서울시 동작구)

- 모든 트랜잭션이 처리되지 않으면 커밋되지 않고 에러 발생!

 

 

 

 1. transaction 

- 데이터베이스의 작업 단위

- 대상 쿼리 : insert, update, delete만 해당

- transaction 대상 쿼리문이 실행될 때마다 HDD에 기록되면 프로그램의 속도가 느려짐

  > Oracle은 속도 향상을 위해서 접속자 세션(memory)에만 정보가 저장됨

 

  * 접속자 세션은 접속자가 비정상 종료를 하면 작업 정보를 저장하지 않고 종료함 > 작업한 내용이 사라짐!

  * 접속자 세션은 같은 테이블을 사용하더라도 다른 접속자가 변경한 내용을 적용받지 못 함

 

- Transaction 완료는 commit 명령으로 처리하고, Transaction 취소는 rollback 명령으로 처리

 

 

 2. commit 

- DCL

- insert, update, delete 쿼리문의 작업을 완료할 때 사용

- 메모리(접속자 세션)에서의 작업을 HDD(파일영역)에 기록하고, 모든 접속자 세션에 변경내역을 통지함

- Oracle은 autocommit을 설정할 수 있음

    * autocommit : Transaction 대상 쿼리문이 실행되면 바로 commit 되는 것.

 

 

 3. rollback 

- DCL

- insert, update, delete 쿼리문의 작업을 취소할 때 사용 (DB 작업 취소)

- savepoint와 같이 사용하면 특정 지점까지 작업을 취소할 수 있음

- commit된 데이터는 rollback 될 수 없음 (HDD에 기록되었으면 취소 불가)

 

- 사용법)

1) 직전 commit 이후의 모든 작업을 취소할 때 : rollback;

2) savepoint와 함께 사용할 때 : rollback to 저장점명;

     -> 아래에서 위로 취소되면서 올라감

 

** savepoint(저장점)

    - rollback이 될 위치를 설정하는 명령

    - commit 되거나 rollback을 수행하면 savepoint는 사라짐

    - 같은 이름의 저장점이 생성되면 이전의 저장점은 사라짐

    - transaction 대상 쿼리문 전에 설정함

    - 문법) savepoint 저장점명;

                 rollback to 저장점명;


# 오늘의 코딩 #

- rollback과 savepoint를 사용한 rollback

 

#test_student table에 savepoint 및 insert를 해봄

savepoint insert_data;
insert into test_student (name, gender, addr, phone_no)
values ('박행복','남','서울시 동대문구','010-2333-2222');

savepoint insert_data2;
insert into test_student (name, gender, addr, phone_no)
values ('황기쁨','여','강원도 강릉시','010-9999-9999');

savepoint insert_data3;
insert into test_student (name, gender, addr, phone_no)
values ('안조조','남','제주도 제주시','010-9999-9933');

 

# savepoint를 사용한 rollback

- savepoint 2까지 rollback하면 (rollback to insert_data2;) 하기와 같이 insert 작업이 취소됨!

#rollback

- rollback(rollback;)을 하면 이전 commit 부분까지 다 취소됨

'Development > Oracle' 카테고리의 다른 글

[Oracle] delete / truncate / drop  (0) 2021.09.18
[Oracle] 산술연산자  (0) 2021.09.16
[Oracle] select / alias / update  (0) 2021.09.13
[Oracle] create / insert  (0) 2021.09.11
[Oracle] Data Type / 주석  (0) 2021.09.10

+ Recent posts