내용 목차
본 절에서는 tbJDBC의 사용법과 JDBC의 기본 기능, 프로그래밍에 대해서 기술한다.
Tibero에서는 Java 프로그램 안에서 SQL 문장을 실행하기 위해 데이터베이스를 연결해주는 애플리케이션 프로그램의 인터페이스를 제공한다. 이러한 인터페이스를 tbJDBC(Tibero의 Java Database Connectivity)라 한다.
tbJDBC는 JDK 버전이 1.4 이상의 환경에서 동작한다. JDBC 4.0을 기능을 모두 사용하기 위해서는 JDK 6 이상의 환경을 사용하여야 한다. JDK 6 이상에서 사용할 수 있는 드라이버 파일은 tibero6-jdbc.jar 파일의 형태로 제공되며, JDK 버전이 1.4인 경우에는 tibero6-jdbc-14.jar 파일의 형태로 제공된다.
본 안내서에서는 JDBC 프로그래밍에 대해 간략히 설명한다. tbJDBC에 대한 자세한 내용은 "Tibero JDBC 개발자 안내서"를 참고한다.
tbJDBC를 사용하기 위해서는 JDK 1.4 이상이 반드시 설치되어 있어야 한다.
다음 위치에서 JDK를 다운로드할 수 있다.
http://www.oracle.com/technetwork/java/javase/downloads/index.html
만약 시스템이 Oracle사의 JDK를 사용하지 않는다면 각각의 시스템에 적합한 JDK를 찾아 설치한다. 예를 들어 HP-UX는 HP, AIX는 IBM에서 JDK를 다운로드 받아 설치하면 된다.
각 시스템별 JDK를 설치하는 방법은 다음 위치에서 확인할 수 있다.
http://www.oracle.com/technetwork/java/index.html
벤더별 JDK 설치 방법은 각 벤더에서 제공하는 설치 안내서를 참고한다.
tbJDBC는 JDBC 4.0 표준을 준수한다. 다만, 표준에 따르면 필수적으로 구현해야하는 부분과 벤더별로 구현여부를 선택 가능한 부분을 구분하여 명시하고 있으며, 이러한 추가 기능에 대해서는 지원하지 않을 수도 있다. 또한 JDBC 4.0은 아래의 JDBC 표준을 모두 포함한다.
JDBC 3.0 API
JDBC 2.0 API(JDBC 2.0 Optional Package API and JDBC 2.1 core API)
JDBC 1.2 API
JDBC 1.0 API
본 절에서는 tbJDBC에서 구현되는 표준 기능을 JDBC 버전 별로 간략히 설명한다. 보다 자세한 내용은 Sun사에서 발행한 JDBC 4.0 Specification 문서를 참고한다.
본 절에서는 JDBC 1.0 및 JDBC 2.0의 표준 기능을 지원 여부에 따라 각각 설명한다.
SQL-99 데이터 타입
tbJDBC는 SQL-99에서 새롭게 추가된 데이터 타입 중에 BLOB와 CLOB만을 지원한다. 따라서 이러한 데이터 타입을 Tibero에서 사용할 때는 다음과 같은 규칙을 따른다.
Blob, Clob 인터페이스는 해당 트랜잭션이 수행 중인 동안만 유효하다.
Blob, Clob 인터페이스는 위치 지시자(LOCATOR)를 통해 구현된다. 위치 지시자는 데이터베이스 서버에 존재하는 데이터의 논리적인 지시자(POINTER)이다.
인터페이스 메소드
지원하는 인터페이스 메소드(Interface Method)는 다음과 같다.
java.sql.Array
java.sql.Blob
java.sql.CallableStatement
java.sql.Clob
java.sql.Connection
java.sql.DatabaseMetaData
java.sql.Driver
java.sql.PreparedStatement
java.sql.ResultSet
java.sql.ResultSetMetaData
java.sql.Statement
java.sql.Struct
정적 초기화를 구현한 드라이버
java.sql.Driver 인터페이스 메소드를 구현한 드라이버 클래스는 정적 초기화 블록(Static block)에서 Drivermanager.registerDriver 메소드를 호출함으로써, 새로 생성한 드라이버 인스턴스를 드라이버 관리자(Driver Manager)에 등록할 수 있다.
SQL-92 Entry Level의 확장 기능
DROP TABLE과 ESCAPE 문을 사용할 수 있다.
데이터베이스 서버에서 지원하는 모든 스칼라 함수를 사용할 수 있다. 스칼라 함수는 DatabaseMetaData 클래스를 통해 확인할 수 있다.
여러 개의 스레드가 java.sql과 javax.sql 패키지 내에 존재하는 객체에 모든 연산을 동시에 수행할 수 있다.
스크롤 가능한 결과 집합(Scrollable ResultSet)
결과 집합을 전 방향 또는 후 방향으로 탐색할 수 있다. 또한 결과 집합 내에서 상대적이거나 절대적인 위치 이동도 할 수 있다.
수정 가능한 결과 집합(Updatable ResultSet)
결과 집합을 수정할 수 있다.
위치 설정을 통한 수정 및 삭제(Positioned Updates and Deletes)
결과 집합의 커서에서 설정한 현재 위치의 레코드를 수정하거나 삭제하는 기능이다.
민감한 결과 집합(Sensitive ResultSet)
결과 집합의 커서가 열린 후에 발생하는 데이터의 변화를 반영할 수 있다.
일괄 수정 작업(Batch Updates)
여러 번의 수정 작업을 한꺼번에 처리할 수 있다.
RowSet 기술
데이터를 편리하게 전달하고 처리할 수 있다.
분산 트랜잭션(Distrubuted transactions)
여러 데이터베이스 서버에 이르는 트랜잭션을 가능하게 한다.
SQL-99 데이터 타입
tbJDBC는 SQL-99 데이터 타입 중에서 Array, Ref, Struct를 지원하지 않는다
인터페이스 메소드
지원하지 않는 인터페이스 메소드는 다음과 같다.
java.sql.Ref
java.sql.SQLData
java.sql.SQLInput
java.sql.SQLOutput
잘린(Truncated) 데이터 대한 예외 상황
JDBC 드라이버가 예기치 않게 데이터 값을 잘라낸 경우 읽기를 할 때에는 Data Truncation 경고, 쓰기를 할 때에는 Data Truncation 예외(Exception)를 발생시킨다.
본 절에서는 JDBC 3.0의 표준 기능을 지원 여부에 따라 각각 설명한다. JDBC 3.0 API는 J2SE platform, version 1.4 이상의 환경에서 사용할 수 있다.
인터페이스
지원하는 인터페이스는 다음과 같다.
java.sql.ParameterMetaData
java.sql.Savepoints
javax.sql.ConnectionEventListener
javax.sql.ConnectionPoolDataSource
javax.sql.DataSource
javax.sql.PooledConnection
javax.sql.RowSet
javax.sql.RowSetInternal
javax.sql.RowSetListener
javax.sql.RowSetMetaData
javax.sql.RowSetReader
javax.sql.RowSetWriter
javax.sql.XAConnection
javax.sql.XADataSource
최대 풀 크기, 최소 풀 크기, 초기 풀 크기 등과 같이 접속 풀링에 사용되는 다양한 파라미터를 설정할 수 있는 API를 제공한다.
접속 풀링과 관련된 문장의 풀링을 제공한다.
ParameterMetaData 인터페이스를 구현한 JDBC 클래스는 준비된 문장(Prepared Statement)에서 사용한 파라미터 개수의 정보를 제공한다. 단, 데이터 타입 및 속성(Property)에 대한 메타데이터(metadata)는 제공하지 않는다.
저장점
Savepoint 인터페이스를 구현하여 트랜잭션에 대한 저장점 설정과 커밋 및 롤백 기능을 제공한다. 단, 특정한 저장점을 해제하는 Connection.releaseSavepoint java.sql 메소드는 제공하지 않는다.
자동 생성 키
SQL 문장을 실행한 후 결과 집합으로부터 getGeneratedKeys
함수를 사용하여 결과 로우에 대한 키 또는 사동으로 생성된 컬럼의 값을 얻는다.
결과 집합의 유지성(ResultSet Holdability)
결과 집합이 열려있는 동안에 커밋이 발생했을 때 결과 집합을 그대로 유지할지 아니면 닫을지를 설정한다. tbJDBC에서는 결과 집합을 유지하는 방법만을 지원한다.
여러 개의 결과 집합 반환
한 SQL 문장이 여러 개의 결과 집합을 열 수 있도록 지원한다.
BLOB와 CLOB 객체에 존재하는 데이터의 수정
updateXXX API를 통해 BLOB와 CLOB 객체에 포함된 데이터를 수정하는 기능을 제공한다.
추가된 데이터 타입
타입 | 설명 |
---|---|
java.sql.Types.DATALINK | URL과 같은 외부 리소스의 접근을 제공한다. |
java.sql.Types.BOOLEAN | BIT 타입과 논리적으로 동일하다. |
REF 객체에 의해 참조된 객체의 검색 및 수정
REF 객체에 의해 참조된 객체를 검색하고, 수정할 수 있는 기능을 제공한다.
그룹 변환 및 데이터 타입의 매핑
JDBC API를 통해 사용자 정의 데이터 타입(UDT: User Defined Types)과 Java 클래스 간의 매핑 관계를 설정할 수 있다. 그러나 Tibero에서는 사용자 정의 데이터 타입을 지원하지 않는다.
본 절에서는 JDBC 4.0의 표준 기능을 지원 여부에 따라 각각 설명한다. JDBC 4.0 API는 Java SE platform, version 6 이상의 환경에서 사용할 수 있다.
인터페이스
지원하는 인터페이스는 다음과 같다.
java.sql.NClob
java.sql.RowId
java.sql.SQLXML
java.sql.Wrapper
javax.sql.StatementEventListener
SQL: 2003에 추가된 XML 데이터 타입 지원
SQLXML 인터페이스를 통해 XML 데이터 타입을 사용할 수 있다.
자동 java.sql.Driver 검출(Auto java.sql.Driver discovery)
Class.forName을 사용한 java.sql.Driver 클래스의 로드 없이도 드라이버 객체를 사용할 수 있다.
국가별 캐릭터 셋(National Character Set) 지원
데이터베이스에서 별도로 지정해 사용하는 국가별 캐릭터 셋을 지원하기 위한 API가 추가되었다.
향상된 SQLException
연쇄적으로 연결된 예외를 생성할 수 있게 되어 보다 자세한 원인을 전달해 줄 수 있으며, 새로운 종류의 예외 타입이 추가되었다.
향상된 Blob/Clob 기능
Blob/Clob 객체를 생성/해제할 수 있는 API를 지원한다.
SQL ROWID 데이터 타입의 지원
RowId 인터페이스를 이용하여 SQL ROWID 타입을 사용할 수 있다.
실제 JDBC 객체에 대한 접근 허용
Wrapper 인터페이스를 이용하여 애플리케이션 서버나 접속 풀링 환경에서도 실제 JDBC 객체에 접근해 사용할 수 있다.
접속 풀링 환경에서 실제 접속 상태에 대한 통지
접속 풀링 환경에서 실제 접속이 닫히거나 유효하지 않게 되었을 때 그 상태를 풀링된 문장에 통지해 준다.
사용자 정의 타입 조회 및 계층 구조 검색
사용자 정의 타입의 속성 및 계층 구조를 조회할 수 있는 API가 추가되었다.
본 절에서는 tbJDBC에서 제공하는 인터페이스 메소드를 통해 기본적인 Java 프로그램을 작성하는 방법을 설명한다. 본 절에서 설명하고 있는 전체 소스 코드는 “Appendix A. tbJDBC 예제”를 참고한다.
다음은 public class가 포함된 JdbcTest 클래스 파일의 일부이다.
[예 2.1] tbJDBC를 사용한 기본 프로그래밍
import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; public class JdbcTest { Connection conn; public static void main(String[] args) throws Exception { JdbcTest test = new JdbcTest(); test.connect(); ... ⓐ ... test.executeStatement(); ... ⓑ ... test.executePreparedStatement(); ... ⓒ ... test.executeCallableStatement(); ... ⓓ ... test.disconnect(); ... ⓔ ... } /* ... 기능별 멤버 함수를 구현한다. */ }
ⓐ JdbcTest라는 클래스를 통해 데이터베이스에 접속한다.
ⓑ ~ ⓓ 여러 종류의 멤버 함수를 수행한다.
ⓔ 데이터베이스 접속을 해제하는 작업을 수행한다.
다음 절부터는 위 예에서 ⓐ ~ ⓔ 사이에 구현된 멤버 함수를 각각 설명한다.
connect 멤버 함수는 기본 드라이버 관리자를 이용하여 데이터베이스에 접속(connection)하는 동작(ⓐ)을 수행한다. Java에서 기본 제공하는 java.sql.DriverManager 클래스를 통해 드라이버 관리자 기능을 사용할 수 있다.
[예 2.2] tbJDBC - 접속
private void connect() throws ClassNotFoundException { Class.forName("com.tmax.tibero.jdbc.TbDriver"); try { conn = DriverManager.getConnection( "jdbc:tibero:thin:@localhost:8629:tibero", "tibero", "tmax"); } catch (SQLException e) { System.out.println("connection failure!"); System.exit(-1); } System.out.println("Connection success!"); }
구현된 내용을 차례대로 설명하면 다음과 같다.
사용할 드라이버에 해당하는 클래스를 지정하여 Class.forName 메소드를 호출한다.
아래에서 드라이버 관리자를 사용하기 전에 사용할 드라이버를 미리 등록하는 과정이다. 사용할 드라이버에 해당하는 클래스의 이름을 지정하여, Java 가상머신이 드라이버 클래스를 로드하도록 한다.
DriverManager.getConnection 메소드를 호출하여 드라이버 관리자를 통해 데이터베이스 연결을 생성한다. 사용자는 DriverManager.getConnection 메소드의 파라미터로 접속할 데이터베이스의 URL과 DB 사용자이름 및 비밀번호를 입력한다. DriverManager 클래스는 URL에 맞는 드라이버를 찾아 접속에 성공할 경우 데이터베이스 연결을 java.sql.Connection 인터페이스의 객체로 돌려준다. 이를 필드 변수 conn 에 할당한다.
드라이버 관리자가 URL에 적합한 드라이버를 찾지 못하거나, 드라이버에서 데이터베이스로의 접속에 실패한 경우에는 SQLException이 throw된다.
tbJDBC에서는 다른 데이터베이스의 클라이언트에서처럼 문장(statement)에 대한 개념이 존재한다. executeStatement 멤버 함수는 이러한 문장을 실행(execution)하는 기능(ⓑ)을 수행한다.
[예 2.3] tbJDBC - 실행
private void executeStatement() throws SQLException
{
String dropTable = "drop table emp";
String createTable = "create table emp (id number, "+
" name varchar(20), salary number)";
String InsertTable = "insert into emp values(1000, 'Park', 5000)";
Statement stmt = conn.createStatement();
try {
stmt.executeUpdate(dropTable);
} catch(SQLException e) {
// if there is not the table
}
stmt.executeUpdate(createTable);
stmt.executeUpdate(InsertTable);
stmt.close();
}
구현된 내용을 차례대로 설명하면 다음과 같다.
또한 준비된 문장(prepared statement)을 이용하면 파라미터를 바인딩하여 원하는 작업을 수행할 수 있다. executePreparedStatement 멤버 함수는 파라미터가 바인딩이 된 질의를 실행하는 기능(ⓒ)을 수행한다.
[예 2.4] tbJDBC - 준비된 문장의 선언과 파라미터 바인딩
private void executePreparedStatement() throws SQLException { PreparedStatement pstmt = conn.prepareStatement("select name from emp where id = ?"); ... ① ... pstmt.setString(1, "1000"); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { System.out.println(rs.getString(1)); } pstmt.close(); }
구현된 내용을 차례대로 설명하면 다음과 같다.
연결에 prepareStatement 메소드를 호출하여 준비된 문장을 생성한다.
java.sql.PreparedStatement 인터페이스 객체로 반환되며, execute(), executeUpdate(), executeQuery() 메소드를 호출하여 실행할 수 있다.
setString(bind_no, bind_value)
메소드를 이용하여
바인딩할 파라미터의 순서를 정하여 값을 설정한다. pstmt.setString(1,
"1000")은 준비된 문장의 첫 번째 파라미터(①)에 대응되는
"1000"이라는 문자열을 바인딩한다.
파라미터의 바인딩이 완료된 후 executeQuery
메소드를 실행하면
결과 집합(ResultSet)를 얻게 된다. 결과 집합은 개념적으로 tbCLI나 tbESQL의 커서와 동일하다. 결과 집합에
getString(column_no)
메소드를 사용하면 실행 결과를 문자열로 확인할
수 있다.
tbJDBC를 이용하여 작성한 프로그램에서 PL/SQL를 호출(call)할 수 있다. 이러한 문장을 호출 가능 문장(callable statement)이라고 한다. executeCallableStatement 멤버 함수는 호출 가능 문장을 실행하는 기능(ⓓ)을 수행한다.
[예 2.5] tbJDBC - 호출
private void executeCallableStatement() throws SQLException
{
String callSQL =
" CREATE PROCEDURE testProc "+
" (ID_VAL IN NUMBER, SAL_VAL IN OUT NUMBER) as " +
" BEGIN" +
" update emp" +
" set salary = SAL_VAL" +
" where id = ID_VAL;" +
" select salary into SAL_VAL" +
" from emp" +
" where id = ID_VAl;" +
" END;";
String dropProc = "DROP PROCEDURE testProc";
Statement stmt = conn.createStatement();
try {
stmt.executeUpdate(dropProc);
} catch(SQLException e) {
// if there is not the procedure
}
stmt.executeUpdate(callSQL);
CallableStatement cstmt = conn.prepareCall("{call testProc(?, ?)}");
cstmt.setInt(1, 1000);
cstmt.setInt(2, 7000);
cstmt.registerOutParameter(2, Types.INTEGER);
cstmt.executeUpdate();
int salary = cstmt.getInt(2);
System.out.println(salary);
stmt.close();
cstmt.close();
}
구현된 내용을 차례대로 설명하면 다음과 같다.
사용할 프러시저를 생성한다. java.sql.Statement 객체를 이용하여 프러시저 생성 SQL 문장을 실행한다.
연결에 prepareCall(str)
메소드를 호출하여 호출 가능 문장을
생성한다. 생성된 호출 가능 문장은
java.sql.CallableStatement 인터페이스 객체로
반환된다.
입력 파라미터와 출력 파라미터를 바인딩한다.
입력 파라미터를 바인딩하는 방법은 setInt(bind_no,
bind_value)
같은 바인딩 메소드(binding method)를 사용하며, 준비된 문장에서와
동일하게 사용할 수 있다.
출력 파라미터에 대해서는 registerOutParameter(bind_no,
type)
메소드를 이용하여 등록한다. 예제에서 등록할 출력 파라미터는 1번에서 생성된 프러시저의 두 번째
파라미터(SAL_VAL IN OUT NUMBER)이다. 이 파라미터는 입출력용으로
선언되었으므로 출력 파라미터로 등록할 수 있다.
executeUpdate
메소드를 호출하여 문장을 실행한 후 출력
파라미터의 타입에 맞는 메소드로 실행 결과를 확인한다. 프러시저의 출력 파라미터는 integer 타입이므로,
CallableStatement 클래스의
getInt(bind_no)
메소드를 이용하여 결과 값을 가져온다.
트랜잭션은 하나 이상의 SQL 문장으로 이루어져 있다. SQL 문장이 실행되면서 전체가 커밋(Commit)되든지 롤백(Rollback)된다. tbJDBC는 Connection 객체에서 트랜잭션을 설정할 수 있다. 초기에는 auto-commit으로 설정되어 있다.
트랜잭션의 처리 모드를 변경하려면 다음과 같이 소스 코드를 추가해야 한다.
conn.setAutoCommit(false); conn.rollback(); conn.commit(); conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITED)