티베로 JDBC 사용법

tbJDBC 사용법을 통해 애플리케이션 프로그램을 개발하는 과정 순서와 데이터 타입, Stream 등을 설명합니다.

개발 과정

아래는 tbJDBC를 사용하여 애플리케이션 프로그램을 개발하는 과정입니다.

  1. 패키지 import 기본이 되는 Java 패키지와 tbJDBC 패키지를 import합니다.

/* 기본 Java 패키지 */ 
import java.sql.*;

/* tbJDBC 패키지 */
import com.tmax.tibero.jdbc.*; 
import com.tmax.tibero.jdbc.ext.*;

  1. 데이터베이스 연결 데이터베이스에 연결하기 위해서 Connection 객체를 생성합니다. Connection 객체를 생성하기 위해서 tbJDBC를 로딩한 후 DriverManager를 이용합니다.

Class.forName("com.tmax.tibero.jdbc.TbDriver");
Connection conn = DriverManager.getConnection
                 ("jdbc:tibero:thin:@localhost:8629:dbsvr", 
                  "tibero", "tmax");

또는 아래와 같이 java.util.Properties를 이용하여 Conneciton할 때 설정 정보를 설정할 수 있습니다.

Class.forName("com.tmax.tibero.jdbc.TbDriver"); 
Properties prop = new Properties(); 
prop.setProperty("user", "tibero"); 
prop.setProperty("password", "tmax"); 
Connection conn =
    DriverManager.getConnection("jdbc:tibero:thin:@localhost:8629:dbsvr", prop);

또는 아래와 같이 DataSource 객체를 이용하여 Connection 객체를 생성합니다.

TbDataSource ds = new TbDataSource(); 
ds.setURL("jdbc:tibero:thin:@localhost:8629:dbsvr");
ds.setUser("tibero"); 
ds.setPassword("tmax");
Connection conn = ds.getConnection();

  1. Statement 객체 생성 데이터베이스에 연결되면, Connection 객체를 이용하여 Statement 객체를 생성합니다.

Statement            stmt = conn.createStatement();
PreparedStatement    pstmt = conn.prepareStatement("SELECT empno, name FROM emp");
CallableStatement    cstmt = conn.prepareCall("BEGIN ... END;");

  1. 질의문 수행과 ResultSet 객체 받기 질의문을 수행하고 ResultSet 객체를 받습니다.

ResultSet rs = stmt.executeQuery("SELECT * FROM ALL_OBJECTS;");

  1. ResultSet 객체 처리 ResultSet 객체는 next() 메소드를 이용하여 모든 로우에 접근할 수 있습니다. 이때 getXXX() 메소드를 호출 하면 원하는 타입별로 로우 데이터를 가져올 수 있습니다. 만약 next() 메소드가 false라면, 더는 결과 집합이 존재하지 않음을 의미합니다.

while (rs.next())
{
    System.out.println(rs.getString(1)); 
    System.out.println(rs.getInt(2));
}

  1. 커밋 또는 롤백 수행 기본적으로 DML 문(INSERT, UPDATE, DELETE)을 수행한 다음에는 자동으로 커밋됩니다. 이러한 기능을 auto-commit이라고 합니다. 사용자는 Connection 클래스에서 제공하는 아래의 메소드를 이용하여 이 기능을 임의로 해제할 수 있습니다.

void setAutoCommit(boolean flag)

이 메소드를 이용하여 auto-commit 기능을 비활성화하면, 사용자는 반드시 DML 문을 사용한 다음 커밋이나 롤백을 수행해야 데이터베이스에 적용됩니다.

conn.commit(); 
conn.rollback();

  1. ResultSet 객체와 Statement 객체 소멸 ResultSet 객체와 Statement 객체는 반드시 소멸시켜야 합니다. 왜냐하면, tbJDBC 내부에는 별도의 finalizer 메소드가 없기 때문입니다. 이 때문에 예상치 못한 시점에 심각한 메모리 누수 현상이 발생할 수 있고, 데이터베이스 내부 커서의 최대 허용 범위를 초과하여 에러가 발생할 수도 있습니다.

rs.close();
stmt.close();

  1. 데이터베이스 연결 해제 마지막으로 모든 작업이 끝나면 반드시 데이터베이스 연결을 해제해야 합니다. 그렇지 않으면 현재 세션이 연결된 상태로 남아 있기 때문에 다음 연결할 때에는 최대 허용 세션을 초과할 수 있으므로 데이터베이스 연결에 실패할 수도 있습니다.

conn.close();


Connection Properties

아래는 DB를 연결할 때에 Properties로 설정할 수 있는 속성들입니다.

속성명
타입
설명

databaseName

String

서버에 존재하는 특정 데이터베이스의 이름

dataSourceName

String

데이터소스의 이름

description

String

데이터소스에 대한 설명

networkProtocol

String

서버와 통신하는 네트워크 프로토콜의 이름 (기본값: TCP)

password

String

서버 접속을 위한 패스워드

user

String

서버 접속을 위한 사용자 이름

portNumber

int

서버 리스너의 포트 번호

serverName

String

데이터베이스의 이름

login_timeout

int

  • 소켓의 read timeout을 지정

  • 최소 소켓을 생성할 때부터 DB 연결 생성이 완료될 때까지 적용

  • DB 연결 생성이 완료된 뒤에는 read_timeout 속성이 적용된다. 만약 응 답이 없이 지정된 시간이 지나면 timeout을 발생시키지만 설정값이 0일 경우에는 timeout을 발생시키지 않음 (단위: millisecond, 기본값: 0)

read_timeout

int

  • DB 연결 생성이 완료된 이후의 소켓의 read timeout을 지정

  • 만약 응답이 없이 지정된 시간이 지나면 timeout을 발생시키지만 설정 값이 0일 경우에는 timeout을 발생시키지 않음 (단위: millisecond, 기본값: 0)

characterset

String

JDBC에서 인코딩, 디코딩 Character Set을 지정 (기본값: 서버의 문자 셋을 사용)

program_name

String

프로그램 이름(기본값: JDBC Thin Client)

includeSynonyms

String

DatabaseMetaData.getColumn()에서 synonyms 객체를 포함할지 여부를 지정 (기본값: false)

mapDateToTimes tamp

String

DATE 컬럼에 대해서 결과 타입으로 Timestamp(true)로 돌려줄지 Date(false)로 여부를 지정 (기본값: true)

defaultNChar

String

PreparedStatement.setString() API로 설정한 문자열을 national charset 설정을 이용하여 서버로 전송하도록 강제함 (기본값: false)

self_keepalive

String

  • SELF KEEP ALIVE 기능을 활성화할지 여부를 지정

  • 활성화한 경우에는 self_keepidle, self_keepintvl, self_keepcnt 속성 설 정에 따라 연결 대상에 대한 네트워크 접근에 문제가 없는지 확인

  • 전체 확인 과정에 실패하면, 해당 네트워크 연결을 강제로 종료시킴 (기본값: false)

self_keepidle

int

  • 접속 완료, DB 요청/응답 처리 등의 정상적인 네트워크 사용 이후, 다음 번의 정상 처리된 시간이 갱신되지 않을 때, 정상 상황으로 간주할 최대 시간을 지정

  • 지정된 시간이 지나면 네트워크 접근에 대한 확인 절차가 시작됨

  • self_keepalive 설정이 true인 경우에만 유효 (단위: 초, 기본값: 60)

self_keepintvl

int

  • 매번 확인할 때의 간격 및 한 번 확인할 때 최대 대기 시간을 지정

  • self_keepalive 설정이 true인 경우에만 유효 (단위: 초, 기본값: 10)

self_keepcnt

int

  • 확인 절차를 총 몇 회까지 수행할 것인지를 지정

  • 지정된 횟수만큼 연속으로 실패하여야만 전체 확인과정이 실패한 것으로 처리됨

  • self_keepalive 설정이 true인 경우에만 유효 (기본값: 3)

failover_retry_count

int

  • Failover 기능이 활성화되었을 때 연결 복원을 시도하는 최대 횟수를 지정 (기본값: 3)

  • Failover 기능에 대한 자세한 설명은 “Failover 및 Load balancing”의 내용을 참고


데이터 타입

tbJDBC는 JDBC 타입을 지원할 뿐만 아니라 Interval 타입을 추가로 제공합니다.

아래는 JDBC 타입과 tbJDBC 타입과의 대응 관계를 나타내는 표입니다.

JDBC 타입(표준)
Java 타입(표준)
tbJDBC 타입

java.sql.Types.CHAR

java.lang.String

java.lang.String

java.sql.Types.VARCHAR

java.lang.String

java.lang.String

java.sql.Types.LONGVARCHAR

java.lang.String

java.lang.String

java.sql.Types.NUMERIC

java.math.BigDecimal

java.math.BigDecimal

java.sql.Types.DECIMAL

java.math.BigDecimal

java.math.BigDecimal

java.sql.Types.BIT

boolean

boolean

java.sql.Types.TINYINT

byte

byte

java.sql.Types.SMALLINT

short

short

java.sql.Types.INTEGER

int

int

java.sql.Types.BIGINT

long

long

java.sql.Types.REAL

float

float

java.sql.Types.FLOAT

double

double

java.sql.Types.DOUBLE

double

double

java.sql.Types.BINARY

byte[]

byte[]

java.sql.Types.VARBINARY

byte[]

byte[]

java.sql.Types.LONGVARBINARY

byte[]

byte[]

java.sql.Types.DATE

java.sql.Date

java.sql.Date

java.sql.Types.TIME

java.sql.Time

java.sql.Time

java.sql.Types.TIMESTAMP

java.sql.Timestamp

java.sql.Timestamp

java.sql.Types.BLOB

java.sql.Blob

com.tmax.tibero.jdbc.TbBlob

java.sql.Types.CLOB

java.sql.Clob

com.tmax.tibero.jdbc.TbClob

java.sql.Types.NCLOB

java.sql.NClob

com.tmax.tibero.jdbc.TbNClob

java.sql.Types.NCHAR

java.sql.NCHAR

java.lang.String

java.sql.Types.NVARCHAR

java.sql.NVARCHAR

java.lang.String

java.sql.Types.SQLXML

java.sql.SQLXML

com.tmax.tibero.jdbc.TbSQLXML

com.tmax.tibero.jdbc.da

ta.DataType.VARRAY

java.sql.Array

com.tmax.tibero.jdbc.TbArray

com.tmax.tibero.jdbc.da

ta.DataType.Struct

java.sql.Struct

com.tmax.tibero.jdbc.TbUpStruct

com.tmax.tibero.jdbc.da ta.DataType.CURSOR

-

com.tmax.tibero.jdbc.TbResultSet

com.tmax.tibero.jdbc.da ta.DataType.ITV_DTS

-

com.tmax.tibero.jdbc.TbIntervalDts

com.tmax.tibero.jdbc.da ta.DataType.ITV_YTM

-

com.tmax.tibero.jdbc.TbIntervalYtm

com.tmax.tibero.jdbc.da ta.DataType.RowId

-

com.tmax.tibero.jdbc.TbRowId

com.tmax.tibero.jdbc.da ta.DataType.TIMESTAMP_TZ

java.sql.Timestamp

com.tmax.tibero.jdbc.TbTimes tampTZ

com.tmax.tibero.jdbc.da ta.DataType.TIMESTAMP_LTZ

java.sql.Timestamp

java.sql.Timestamp

Tibero에서 TIME 데이터 타입을 지원하지만 DATE 데이터 타입을 사용하기를 권장합니다. TIME 컬럼에 대해서 PreparedStatement.setTime() 메소드로 지정할 수 없습니다. PreapredStatement.setTime()은 DATE 데이터 타입의 컬럼에 대해서 지원하고 있습니다. TIME 컬럼에 대한 값을 지정하기 위해 서는 문자열을 TIME 값으로 변환하는 TO_TIME 함수를 통해서 입력할 수 있습니다.


tbJDBC Stream

tbJDBC에서는 특정 데이터 타입에 대해 아래와 같은 Stream 기능을 제공합니다.

  • 컬럼에 대한 Stream 생성 - CHAR, VARCHAR, RAW, NCHAR, NVARCHAR - LONG, LONG RAW - LOB

  • Stream 소멸

tbJDBC에서는 아래와 같이 4종류의 Stream 메소드를 제공합니다.

메소드
반환값
설명

getAsciiStream

Java.io.InputStream

ASCII 형태로 변환된 데이터 Stream

getBinaryStream

Java.io.InputStream

byte 형태로 변환된 데이터 Stream

getUnicodeStream

Java.io.InputStream

Unicode 형태로 변환된 데이터 Stream 이 메소드 는 JDBC 4.0에서 폐기(deprecated)되었으므로 호환성을 고려하여 가급적 사용하지 않는 것이 좋음

getCharacterStream

Java.io.Reader

문자열 형태로 변환된 데이터 Reader

각각의 메소드를 이용하면 해당 데이터 타입에서 허용하는 최대 크기까지 점진적으로 데이터를 읽을 수 있습니다. 메소드에서 반환되는 객체는 InputStream과 Reader이고, read() 메소드를 사용하면 데이터를 읽을 수 있습니다.

컬럼에 대한 Stream 생성

CHAR, VARCHAR, RAW 컬럼에 Stream 메소드를 사용하는 경우 전체 데이터를 한꺼번에 받아와서 Stream 객체로 생성합니다. 반면, LONG이나 LONG RAW, LOB 컬럼에 대해서는 최초 일부의 데이터만 읽어온 후 Stream 객체를 생성합니다. 단, 사용자가 추가로 요청하면 차례대로 데이터를 더 읽어온 후 Stream 객체를 생성하게 됩니다.

아래는 getBinaryStream()을 이용하여 데이터를 읽어오는 예입니다.

ResultSet rs = stmt.executeQuery("SELECT name, image FROM backgrounds");

while (rs.next()) {
    InputStream imageIS = rs.getBinaryStream(2); 
    try {
        FileOutputStream fos = new FileOutputStream(rs.getString(1)); 
        int chunk = 0;
        while ((chunk = imageIS.read()) != -1) 
            fos.write(chunk);
    }
    catch (Exception e) 
        { e.printStackTrace();
    }
    finally {
        if (fos != null) 
        fos.close();
    }
}

아래는 getBinaryStram() 대신 getBytes()를 이용하여 데이터를 읽어오는 예입니다.

ResultSet rs = stmt.executeQuery("SELECT name, image FROM backgrounds");
while (rs.next()) {
    bytes[] images = rs.getBytes(2); 
    try {
        FileOutputStream fos = new FileOutputStream(rs.getString(1)); 
        fos.write(images);
    }
    catch (Exception e) 
        { e.printStackTrace();
    }
    finally {
        if (fos != null) 
            fos.close();
    }
}


내장 함수 호출

PSM의 사용

tbJDBC에서는 PSM을 사용할 수 있습니다.

아래와 같이 SQL-92의 ESCAPE 문법과 PSM 문법을 제공합니다.

/ SQL92 ESCAPE 문법
CallableStatement cstmt = conn.prepareCall("{call proc(?)}"); 
CallableStatement cstmt = conn.prepareCall("{? = call func(?)}");

// PSM 문법
CallableStatement cstmt = conn.prepareCall("begin proc(?); end;"); 
CallableStatement cstmt = conn.prepareCall("begin ? := func(?); end;");

아래는 PSM 문법을 사용하여 내장 함수를 호출하는 예입니다.

create or replace function concat(x varchar2, y varchar2)
return varchar2 is 
begin
    return x || y; 
end;
CallableStatement cstmt = conn.prepareCall("begin ? := concat(?, ?); end;");

cstmt.regiterOutParameter(1, Types.VARCHAR); 
cstmt.setString(2, "Tmax"); 
cstmt.setString(3, "Tibero");
cstmt.executeUpdate();

String result = cstmt.getString(1);

Java Stored Procedure의 사용

이전 절에서 설명한 방법과 같이 Java Stored Procedure를 사용할 수 있습니다.

Java Stored Procedure에 대한 자세한 내용은 "Tibero External Procedure 안내서"를 참고합니다.


예외 처리

tbJDBC에서는 예외 상황을 처리하기 위해 java.sql.SQLException 클래스 객체를 정의할 수 있습니다. 예외 상황은 tbJDBC 내부에서 발생할 수도 있고, 데이터베이스 내부에서 발생할 수도 있습니다. 예외 상황의 내용은 에러 코드와 에러가 발생한 위치 등의 정보가 포함되어 있습니다.

예외 상황에 대한 정보를 얻기 위해 다음과 같은 메소드가 제공됩니다.

메소드
설명

getMessage()

에러가 발생한 원인

getSQLState()

SQL 상태 정보

getErrorCode()

에러 코드

printStackTrace()

에러가 발생한 스택의 트레이스 정보(Stack trace)

아래는 위의 메소드를 사용하여 예외 상황을 처리하는 예입니다.

try {
    stmt.execute("drop table not_exist_table");
}
catch (SQLException e) {
    System.out.println("ERROR[" + e.getErrorCode() + "]" + e.getMessage()); 
    e.printStackTrace();
}

실행하면 아래와 같은 정보가 화면에 출력됩니다.

ERROR[-7071] Schema object'NOT_EXIST_TABLE' was not found or is invalid. 
java.sql.SQLException: Schema object 'NOT_EXIST_TABLE' was not found or is invalid.
    at com.tmax.tibero.jdbc.msg.common.TbMsgError.readErrorStackInfo(TbMsgError.java
:108)
    at com.tmax.tibero.jdbc.msg.TbMsgEreply.deserialize(TbMsgEreply.java:61)
    at com.tmax.tibero.jdbc.comm.TbStream.readMsgBody(TbStream.java:327)
    at com.tmax.tibero.jdbc.comm.TbCommType4.executeDirect(TbCommType4.java:460) 
    at com.tmax.tibero.jdbc.TbStatement.executeInternal(TbStatement.java:1051) 
    at com.tmax.tibero.jdbc.TbStatement.execute(TbStatement.java:560)
    at TestSimple.main(TestSimple.java:102)

Last updated