JDBC 드라이버 연결

티베로 JDBC 드라이버 연동에 대해 설명합니다.

JDBC 개념

JDBC는Java Database Connectivity의 약자로서 Java로 만들어진 클래스와 인터페이스로 이루어진 API입니다.

DBMS의 종류와 관련없는 독립적인 프로그래밍을 가능하게 해주며 JDBC는 java.sql, javax.sql 두 개의 패키지에 포함됩니다.

  • java.sql은 데이터베이스에 접근하고 데이터를 검색하거나 업데이트하는 핵심 JDBC API를 제공합니다.

  • javax.sql은 JDBC 클라이언트가 서버측의 데이터소스를 접근할 수 있게 하는 API를 제공합니다.

JDBC Driver Types

Type 1 : JDBC-ODBC Bridge Driver

ODBC 같이 다른 Data Access API와 매핑하는 형태의 JDBC API를구현한 것 입니다. 이것은 Native Client Library에 종속적으로 되는경우가 많아 이식성에 제약이 있습니다. Sun의 JDBC-ODBC Bridge Driver가 이에 속하지만 JDBC 3.0의 지원이나 멀티쓰레딩을 사용할 수 없는 등 여러가지 제약을 갖습니다.

[그림 9] Type 1_ JDBC-ODBC Bridge Driver

[그림 9] Type 1_ JDBC-ODBC Bridge Driver

Type 2 : Native-API Driver

Native Code와 Java Code가 혼합되어 구현이 되어있습니다. 주로 Interface만 Java인 경우가 많고 접근하는 데이터소스 에 따라 각기 다른 Native Client Library가 필요합니다. 그래서 이것을 Thick Driver 라고도 합니다. Native Code로 인하여 이식성에 제한이 있습니다.

[그림 10] Type 2_Native-API Driver

[그림 10] Type 2_Native-API Driver

Type 3 : Net-Protocol Driver

데이터베이스에 독립적인 프로토콜을 이용하는 미들웨어 서버와 통신하고 순수 자바 클라이언트를 사용하는 드라 이버로, 미들웨어 서버는 클라이언트의 요청을 데이터소스에 독립적인 프로토콜로 변환하여 사용합니다.

이 경우 드라이버가 직접 데이터베이스를 제어하지 않고 미들웨어를 통하여 제어하기 때문에 유연성을 갖습니다.

[그림 11] Type 3_Net-Protocol Driver

[그림 11] Type 3_Net-Protocol Driver

Type 4 : Native-Protocol Driver

모두 자바로 구현되어 있어 플랫폼에 제한을 받지 않으며 별도의 클라이언트 소프트웨어가 없이 표준 자바 소켓을 이용하여 데이터소스와 직접 통신합니다. 일반적으로 Thin Driver라고 합니다.

[그림 12] Type 4_Native-Protocol Driver

[그림 12] Type 4_Native-Protocol Driver


Tibero JDBC

본 절에서는 JDBC 드라이버 설명과 연동하는 방법에 대해서 설명합니다.

Tibero에서는 현재 Type 4(Native-Protocol Driver)만 지원합니다.

JDBC 드라이버

JDBC 드라이버는 "$TB_HOME/client/lib/jar" 경로에 존재합니다.

아래는 드라이버 파일에 대한 설명입니다.

  • 파일명 규칙

tibero[DB_MAJOR_VERSION]-jdbc-[JDK_VERSION]-[DEBUG].jar
항목
설명

[DB_MAJOR_VERSION]

Tibero 제품의 메인 버전을 표시합니다.

[JDK_VERSION]

JDBC 드라이버가 동작하는 JDK 버전을 표시합니다. 기본형의 경우 생략합니다.

[DEBUG]

문제가 발생할 때 로그를 발생하는 JDBC 파일(디버그 용도)인지 알려줍니다.

  • 사용 예

파일명
설명

tibero7-jdbc.jar

JDK(또는 JRE) 1.6 이상에서 수행 가능한 드라이버 파일(기본형)입니다.

tibero7-jdbc-dbg.jar

JDK(또는 JRE) 1.6 이상에서 수행 가능한 JDBC 파일(디버그 용도)입니다.

tibero7-jdbc-14.jar

JDK(또는 JRE) 1.4 이상에서 수행 가능한 드라이버 파일(JRE 버전 문제가 발생할 경우 주로 사용)입니다.

tibero7-jdbc- 14.dbg.jar

JDK(또는 JRE) 1.4 이상에서 수행 가능한 JDBC 파일(디버그 용도)입니다.

버전 확인

주로 JDBC 리비전 정보가 필요할 때 아래와 같은 방법으로 확인할 수 있습니다.

  • 형식

java -jar [driver_name]
항목
설명

[driver_name]

JDBC 드라이버 파일명입니다.

  • 사용 예

$ java -jar tibero7-jdbc.jar

Tibero JDBC Driver 7.0 (develop) (Rev.1e6bd49823)

Copyright 2020 TmaxTibero Co., Ltd. All Rights Reserved.

Patch files (none)

드라이버 연동

Tibero JDBC를 가지고 서버와 연동할 때 연동할 때 아래의 클래스를 사용합니다.

  • Connection을 맺을 때 사용하는 클래스명 com.tmax.tibero.jdbc.TbDriver

  • 데이터소스 사용 시 클래스명 com.tmax.tibero.jdbc.ext.TbConnectionPoolDataSource

  • XA 데이터소스 사용 시 클래스명 com.tmax.tibero.jdbc.ext.TbXADataSource

데이터베이스 URL

데이터베이스 URL은 Single 노드 구서오가 TAC 노드 구성으로 나누어 설명합니다.

Single 노드 구성

1개의 Tibero 서버로 구성된 경우입니다.

  • 사용 방법

jdbc:tibero:thin:@<ip>:<port>:<db_name>
항목
설명

< ip >

접속하려는 Tibero 서버의 IP 주소입니다.

< port >

접속하려는 Tibero 서버 포트 번호입니다.

< db_name >

접속하려는 Tibero 서버 DB 이름입니다.

  • 사용 예

jdbc:tibero:thin:@192.168.17.24:7777:tibero

TAC 노드 구성

2개로 구성된 TAC 서버일 경우입니다.

  • 사용 방법

jdbc:tibero:thin:@(description=
    (failover=on)(load_balance=on)
    (address_list=(address=(host=<node1_ip>)(port=<node1_port>))
                  (address=(host=<node2_ip>)(port=<node2_port>))
    )(DATABASE_NAME=<db_name>))
항목
설명

failover

연결이 끊어진 경우 자동으로 복구해주는 기능(on 또는 off 설정)으로, 순차적 방식으로 새로운 서버에 접속하며 현재는 데이터베이스와의 연결만 복구합니다.

load_balance

사용자 Connection을 여러 서버로 분산시키는 기능(on 또는 off 설정)으로, Dedicate 방식(=전용방식)으로 구성할 경우 해당 기능을 off 합니다.

< node1_ip >

< node1_port >

1번 노드에 대한 접속 정보입니다. (IP 주소, 포트 번호)

< node2_ip >

< node2_port >

2번 노드에 대한 접속 정보입니다. (IP 주소, 포트 번호)

< db_name >

접속하려는 TAC의 DB 이름입니다.

  • 사용 예

jdbc:tibero:thin:@(description=
    (failover=on)(load_balance=on)
    (address_list=(address=(host=192.168.17.24)(port=10010))
                  (address=(host=192.168.17.24)(port=10020))
    )(DATABASE_NAME=<db_name>))


JDBC 전환

본 장에서는 Oracle JDBC를 전환하는 내용을 설명합니다.

Oracle JDBC

클래스를 변경할 때 아래를 참고합니다.

Oracle
Tibero

oracle.jdbc.driver.OracleTypes.CURSOR

com.tmax.tibero.TbTypes.CURSOR

oracle.sql.BLOB

com.tmax.tibero.jdbc.TbBlob

oracle.sql.CLOB

com.tmax.tibero.jdbc.TbClob

oracle.jdbc.driver.OracleResultSet

com.tmax.tibero.jdbc.TbResultSet

oracle.jdbc.OracleCallableStatement

com.tmax.tibero.jdbc.TbCallableStatement


문제 해결

특정 문제가 발생했을 때 해결하는 방법을 설명합니다.

로그 발생

Tibero JDBC를 사용하여 특정 문제가 발생했을 때 추가적인 로그를 발생하여 확인하는 방법입니다.

로그가 추가적으로 발생하므로 일부 성능이 느려질 수 있으므로, 문제가 있을 때 일시적으로만 사용합니다.

로그 발생은 아래와 같은 순서로 적용합니다.

  1. 드라이버 교체 기존에 사용하던 JDBC 드라이버 파일을 tibero7-jdbc-dbg.jar와 같은 디버그 용도 파일로 교체합니다.

  2. 클라이언트 프로그램 재기동 디버그 용도 파일을 가지고 동작할 수 있도록 프로그램을 재기동합니다.

  3. 로그 파일 위치 확인(해당 폴더 확인) UNIX 계열 : /home/사용자 이름

  4. 로그 파일 이름 확인 tbjdbc-{yyMMdd}-{HHmmss}-{S}-{random}.log 형식으로 파일이 생성됩니다.


예제

본 절에서는 JDBC를 이용하여 연결하는 기본적인 형태의 예제와 특수한 타입의 예제를 설명합니다.

기본 예제

아래는 JDBC를 이용한 연결 예제입니다.

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.tmax.tibero.jdbc.ext.TbDataSource;

public class TiberoJDBC {

    public static void main(String[] args) throws SQLException { 
    
        TbDataSource tds = new TbDataSource();
        tds.setURL("jdbc:tibero:thin:@127.0.0.1:8629:t5");
        tds.setUser("dbtech");
        tds.setPassword("dbtech");
        
        Connection conn = tds.getConnection();
        Statement stmt = conn.createStatement();
        
        String query = "select table_name from user_tables where rownum < 10 " ; 
        ResultSet rs = stmt.executeQuery(query);

        String sTname=null; 
       
        int irows = 1;
        while ( rs.next() ) {
            sTname = rs.getString("table_name");
            System.out.println("row[" + irows + "] : " + sTname); 
            irows++;
        }
        rs.close(); 
        stmt.close(); 
        conn.close(); 
     }
}

타입 관련 예제

NVARCHAR 처리

com.tmax.tibero.jdbc.TbPreparedStatement에 NCharset을 지원하기 위해 아래와 같은 API를 제공합니다.

  • setNCharacterStream()

  • setNClob()

  • setNString()

아래는 NVARCHAR 처리의 예제입니다.

ds = (DataSource)ctx.lookup("tibero"); 
conn = ds.getConnection();

ins_pstmt = (TbPreparedStatement)conn.prepareStatement(ins_query);
ins_pstmt.setString(1, "test");
ins_pstmt.setNString(2, "multinational character");

ARRAY

동일한 타입의 Primitive 값이 Array인 경우에만 지원이 가능합니다.

  • 테스트 오브젝트 생성

CREATE OR REPLACE PACKAGE TYPE_PKG
AS
    TYPE "TY_CHOICE_IDX_ARR" IS VARRAY(20000) OF CLOB; 
END;
/
CREATE OR REPLACE PROCEDURE TB_ARRAY_TEST 
(
  I_INPT_EXPC_DIV IN VARCHAR2,
  ....
  O_CHOICE_PACKET OUT TYPE_PKG.TY_CHOICE_IDX_ARR /* TYPE */ 
)
IS
  .....
  L_DATA TYPE_PKG.TY_CHOICE_IDX_ARR; 
  TMP_CLOB_RTN CLOB;
  BEGIN 
  -- init
  L_DATA := TYPE_PKG.TY_CHOICE_IDX_ARR(); 
  TYPE AAA_SET IS TABLE OF CBT_CAT%ROWTYPE; 
  AAA AAA_SET;
....
  FOR I IN AAA.FIRST .. AAA.LAST 
  LOOP
     -- CLOB return function
     T_CHOICE_IDX_LIST := FN_CHOICE_LIST_ADD_01();
     O_CHOICE_IDX_LIST := O_CHOICE_IDX_LIST || T_DELIM_PIPE || T_CHOICE_IDX_LIST; 
  END LOOP;
  L_DATA.EXTEND;
  L_DATA(L_DATA.COUNT) := O_CHOICE_IDX_LIST || 'FALSE' || 'string test' 
  O_CHOICE_PACKET := L_DATA;
END; 
/

  • 예제 소스(소스 일부)

CallableStatement cstmt = null; 
Array packetArray = null;

callableSql = "begin ? :=TB_ARRAY_TEST(?,?,?,?,?); end;"; 

try{
   cstmt = (CallableStatement)con.prepareCall(callableSql);
   cstmt.setString(1, domainCd.trim());
   cstmt.setString(2, tsNo.trim());
   cstmt.setDouble(3, Double.parseDouble(verNo.trim()));
   cstmt.setString(4, inptExpcDiv);
   cstmt.setString (5, choiceGrpNo);
   //out parameter
   cstmt.registerOutParameter(6, TbTypes.ARRAY, "TYPE_PKG.TY_CHOICE_IDX_ARR" ); 
   cstmt.execute();
   packetArray = cstmt.getArray(6); 

   // Get the ARRAY object
     if(packetArray == null){
       throw new BCException("no data"); 
     }
     Object o = packetArray.getArray();
     clobs = (Clob[])o;
     choiceGrpPacketList = new ArrayList(clobs.length); 
     Clob clob = null;
     String packet = null; 
     long clobLength = 0;
     for( int i = 0 ; i < clobs.length; i++ ){ 
       clob = clobs[i];
       clobLength = clob.length();
       packet = clob.getSubString(1, (int)clobLength);
       choiceGrpPacketList.add(JdbcCodeConvertor.toKor(packet)); 
     }
   }catch(SQLException sqle){ 
     sqle.printStackTrace();
   }finally{
     if( cstmt != null ){ 
       try{
         cstmt.close();
       }catch(SQLException sqle) {
         logger.error("CallableStatement close Error !"); 
         sqle.printStackTrace();
       } 
     }
}

Last updated