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 예정


# 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) 오류 발생 시 에러 메시지(이름 : 김동동 / 주소 : 서울시 동작구)
- 모든 트랜잭션이 처리되지 않으면 커밋되지 않고 에러 발생!

'Development > JDBC' 카테고리의 다른 글
| [JDBC] Cursor 작성 예정 (0) | 2021.10.21 |
|---|---|
| [JDBC] Procedure 호출 / in parameter / out parameter / CallableStatement 활용 (0) | 2021.10.20 |
| [JDBC] DAO / PreparedStatement 활용 (0) | 2021.10.15 |
| [Java/JDBC] Singleton Pattern (0) | 2021.10.14 |
| [JDBC] SQL Exception / SQL Injection (0) | 2021.10.13 |
