티베로 JDBC 사용법
tbJDBC 사용법을 통해 애플리케이션 프로그램을 개발하는 과정 순서와 데이터 타입, Stream 등을 설명합니다.
개발 과정
아래는 tbJDBC를 사용하여 애플리케이션 프로그램을 개발하는 과정입니다.
패키지 import 기본이 되는 Java 패키지와 tbJDBC 패키지를 import합니다.
/* 기본 Java 패키지 */
import java.sql.*;
/* tbJDBC 패키지 */
import com.tmax.tibero.jdbc.*;
import com.tmax.tibero.jdbc.ext.*;
데이터베이스 연결 데이터베이스에 연결하기 위해서 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();
Statement 객체 생성 데이터베이스에 연결되면, Connection 객체를 이용하여 Statement 객체를 생성합니다.
Statement stmt = conn.createStatement();
PreparedStatement pstmt = conn.prepareStatement("SELECT empno, name FROM emp");
CallableStatement cstmt = conn.prepareCall("BEGIN ... END;");
질의문 수행과 ResultSet 객체 받기 질의문을 수행하고 ResultSet 객체를 받습니다.
ResultSet rs = stmt.executeQuery("SELECT * FROM ALL_OBJECTS;");
ResultSet 객체 처리 ResultSet 객체는 next() 메소드를 이용하여 모든 로우에 접근할 수 있습니다. 이때 getXXX() 메소드를 호출 하면 원하는 타입별로 로우 데이터를 가져올 수 있습니다. 만약 next() 메소드가 false라면, 더는 결과 집합이 존재하지 않음을 의미합니다.
while (rs.next())
{
System.out.println(rs.getString(1));
System.out.println(rs.getInt(2));
}
커밋 또는 롤백 수행 기본적으로 DML 문(INSERT, UPDATE, DELETE)을 수행한 다음에는 자동으로 커밋됩니다. 이러한 기능을 auto-commit이라고 합니다. 사용자는 Connection 클래스에서 제공하는 아래의 메소드를 이용하여 이 기능을 임의로 해제할 수 있습니다.
void setAutoCommit(boolean flag)
이 메소드를 이용하여 auto-commit 기능을 비활성화하면, 사용자는 반드시 DML 문을 사용한 다음 커밋이나 롤백을 수행해야 데이터베이스에 적용됩니다.
conn.commit();
conn.rollback();
ResultSet 객체와 Statement 객체 소멸 ResultSet 객체와 Statement 객체는 반드시 소멸시켜야 합니다. 왜냐하면, tbJDBC 내부에는 별도의 finalizer 메소드가 없기 때문입니다. 이 때문에 예상치 못한 시점에 심각한 메모리 누수 현상이 발생할 수 있고, 데이터베이스 내부 커서의 최대 허용 범위를 초과하여 에러가 발생할 수도 있습니다.
rs.close();
stmt.close();
데이터베이스 연결 해제 마지막으로 모든 작업이 끝나면 반드시 데이터베이스 연결을 해제해야 합니다. 그렇지 않으면 현재 세션이 연결된 상태로 남아 있기 때문에 다음 연결할 때에는 최대 허용 세션을 초과할 수 있으므로 데이터베이스 연결에 실패할 수도 있습니다.
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 타입과의 대응 관계를 나타내는 표입니다.
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
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()를 이용하여 데이터를 읽어오는 예입니다.
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를 사용할 수 있습니다.
예외 처리
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