LOB 데이터 처리

tbJDBC에서 LOB 데이터를 처리하는 방법을 설명합니다.

JDBC 표준에서는 LOB 데이터를 처리하기 위해 두 가지 타입을 제공합니다. BLOB(바이너리 데이터)와 CLOB(문자열 데이터)가 이에 해당합니다. tbJDBC에서는 이 두 가지 타입을 효율적으로 처리하기 위해 지시자(locator)라는 개념을 사용합니다.

일반적으로 LOB 데이터는 데이터베이스에 저장된 후에 지시자를 생성하여 데이터가 저장된 위치를 찾아갈 수 있도록 합니다. 따라서 사용자는 이 지시자만을 사용하여 필요할 때마다 LOB 데이터를 읽고 쓸 수 있습니다. 이로써 시스템 성능을 향상시키는 데 도움을 줄 수 있습니다.

tbJDBC에서 제공하는 LOB 클래스

  • com.tmax.tibero.jdbc.TbBlob

  • com.tmax.tibero.jdbc.TbClob

LOB 지시자

LOB 지시자 얻어오기

JDBC 표준에서 제공하는 ResultSet 객체나 CallableStatement 객체의 메소드를 이용하여 LOB 지시자를 얻어올 수 있습니다.

ResultSet 객체

ResultSet.getBlob() 
ResultSet.getClob() 
ResultSet.getObject()

아래는 ResultSet 객체를 이용하여 LOB 지시자를 얻어오는 예 입니다.

ResultSet rs = stmt.executeQuery("SELECT document, image FROM library"); 
while (rs.next())
{
    Clob document = rs.getClob(1);
    // 또는 Clob document = (Clob)rs.getObject(1);
    
    Blob image = rs.getBlob(2);
    // 또는 Blob image = (Blob)rs.getObject(1);
}

CallableStatement 객체

CallableStatement.getBlob() 
CallableStatement.getClob() 
CallableStatement.getObject()

아래는 CallableStatement 객체를 이용하여 LOB 지시자를 얻어오는 예 입니다.

CallableStatement cstmt = conn.prepareCall("{call proc(?)}"); 
cstmt.registerOutParameter(1, Types.CLOB);
cstmt.execute();

Clob document = cstmt.getClob(1);
// 또는 Clob document = (Clob)cstmt.getObject(1);

LOB 지시자 넘겨주기

JDBC 표준에서 제공하는 PreparedStatement 객체나 CallableStatement 객체의 메소드를 이용하여 LOB지시자를 넘겨줄 수 있습니다.

PreparedStatement 객체

PreparedStatement.setBlob() 
PreparedStatement.setClob() 
PreparedStatement.setObject()

아래는 PreparedStatement 객체를 이용하여 LOB 지시자를 넘겨주는 예 입니다.

PreparedStatement pstmt = conn.prepareStatement("INSERT INTO library 
VALUES (?, ?)");

pstmt.setClob(1, document);
// 또는 pstmt.setObject(1, document, Types.CLOB);

pstmt.setBlob(2, image);
// 또는 pstmt.setObject(1, image, Types.BLOB);

pstmt.executeUpdate();

CallableStatement 객체

CallableStatement.setBlob() 
CallableStatement.setClob() 
CallableStatement.setObject()

아래는 CallableStatement 객체를 이용하여 LOB 지시자를 넘겨주는 예 입니다.

CallableStatement cstmt = conn.prepareCall("{call proc(?, ?)}");

cstmt.setClob(1, document);
// 또는 cstmt.setObject(1, document, Types.CLOB);

cstmt.setBlob(2, image);
// 또는 cstmt.setObject(1, image, Types.BLOB);

cstmt.execute();


LOB 데이터 읽고 쓰기

LOB 지시자를 얻어오면 JDBC 표준에서 제공하는 API를 이용하여 데이터를 읽고 쓸 수 있습니다. LOB 데이터는 보통 Byte 배열이나 스트림 형태로 읽어올 수 있는데, 일반적인 스트림 형태와 달리 데이터베이스 서버 내부에 데이터가 있으므로 연결이 유지되는 한 언제든지 접근할 수 있습니다.

JDBC 표준에서는 LOB 데이터를 읽고 쓸 수 있도록 아래와 같은 API를 제공합니다.

  • InputStream Clob.getAsciiStream()

  • Reader Clob.getCharacterStream()

  • String Clob.getSubString()

  • OutputStream Clob.setAsciiStream()

  • Writer Clob.setCharacterStream()

  • int Clob.setString()

  • InputStream Blob.getBinaryStream()

  • byte[] Blob.getBytes()

  • OutputStream Blob.setBinaryStream()

  • int Blob.setBytes()

아래는 LOB 데이터를 읽는 예 입니다.

// BLOB 데이터
InputStream is = image.getBinaryStream(); 
byte[] imageData = new byte[1000]
int readLength = is.read(imageData);

// CLOB 데이터
Reader reader = document.getCharacterStream(); 
char[] docData = new char[1000];
int readLength = reader.read(docData, 0, docData.length);

아래는 LOB 데이터를 쓰는 예입니다.

// BLOB 데이터
byte[] imageData = {32, 53, 78, 19, 2, 93}; 
OutputStream os = image.setBinaryStream(); 
os.write(imageData);

// CLOB 데이터
char[] docData = {'J', 'D', 'B', 'C', '안', '내', '서'};
Writer writer = document.setCharacterStream(); 
writer.write(docData);
writer.flush(); 
writer.close();

위의 예에서 OutputStream이나 Writer 객체는 데이터를 쓸 때마다 데이터베이스에 직접 전송되므로 별도의 UPDATE 문장을 실행할 필요가 없습니다. 그러나 LOB 자체는 트랜잭션 범위에 포함되므로 반드시 커밋을 수행해야 데이터베이스에 최종적으로 반영됩니다.


임시 LOB

tbJDBC에서는 대용량 데이터를 LOB 형태로 저장하기 위해 임시 LOB을 제공합니다. 단, 이 대용량 데이터는 테이블에 저장되지 않습니다.

이를 위해 아래와 같은 메소드를 제공합니다.

  • Connection.createBlob() return Blob

  • Connection.createClob() return Clob

  • Connection.createNClob() return NClob

  • Blob.free()

  • Clob.free()

  • NClob.free()

임시 LOB을 사용하여 저장한 데이터는 임시 테이블 스페이스에 저장됩니다. 이 영역에 저장된 데이터가 더는 필요하지 않게 되면, 사용자는 반드시 이것을 해제해야 합니다. 그렇지 않으면 이 영역의 데이터는 계속 남아있게 됩니다.

임시 LOB는 LOB 컬럼의 데이터를 바인딩할 때 주로 사용합니다. 예를 들면 아래와 같습니다.

PreparedStatement pstmt = conn.prepareStatement("INSERT INTO 
library VALUES (?, ?)");
pstmt.setInt(1, 20090811);

Clob doc = conn.createClob();
doc.setString(1, "JDBC Guide<br>writer:Rachael<br>proofreader:Patrick"); 
pstmt.setClob(2, doc);
pstmt.executeUpdate();

doc.free(); 
pstmt.close();

위에서 나열한 메소드들은 JDBC 표준 API들로 일부 메소드는 Java 버전에 따라 사용할 수 없는 것들이 존재합니다. 이를 위해 tbJDBC에서는 별도로 다음과 같은 구현 메소드들을 제공하고 있습니다. 이 메소드들을 이용할 경우 다른 JDBC와의 호환성은 떨어지지만 tbJDBC에 한하여 Java 버전에 관계 없이 사용할 수 있는 장점이 있습니다.

  • TbConnection.createTbBlob() return TbBlob

  • TbConnection.createTbClob() return TbClob

  • TbConnection.createTbNClob() return TbNClob

Tibero 4.0 SP1까지의 tbJDBC에서는 구현 메소드를 아래와 같은 형태로 제공하였으나, 호환성 문제로 폐기(deprecated)하고 위의 메소드들로 대체되었습니다.

  • static TbBlob.createTemporary(Connection conn) return TbBlob

  • static TbClob.createTemporary(Connection conn) return TbClob

  • static TbClob.createTemporaryNClob(Connection conn) return TbClob

  • TbBlob.freeTemporary()

  • static TbBlob.freeTemporary(TbBlob blob)

  • TbClob.freeTemporary()

  • static TbClob.freeTemporary(TbClob clob)

  • TbNClob.freeTemporary()

  • static TbNClob.freeTemporary(TbNClob nclob)


API 목록

표준 API

LOB와 관련된 표준 API의 정보는 JDBC 표준 문서를 참고합니다.

확장 API

tbJDBC에서는 LOB와 관련된 API로 BLOB, CLOB, NCLOB 메소드를 추가로 제공합니다.

CONNECTION API

TbConnection 클래스에서는 아래와 같은 API를 추가로 제공합니다.

API
설명

TbBlob createTbBlob()

데이터베이스에 임시 BLOB을 생성한 후에 TbBlob 객체를 반환

TbClob createTbClob()

데이터베이스에 임시 CLOB을 생성한 후에 TbClob 객체를 반환

TbNClob createTbNClob()

데이터베이스에 임시 NCLOB을 생성한 후에 TbNClob 객체를 반환

BLOB API

TbBlob 클래스에서는 아래와 같은 API를 추가로 제공합니다.

API
설명

TbBlob createEmptyBlob()

EMPTY_BLOB을 생성하여 반환

void close()

BLOB을 닫음

OutputStream getBinaryOutput

Stream()

setBinaryStream(1L)과 동일

OutputStream getBinaryOutput

Stream(long)

setBinaryStream(long)과 동일

void open(int)

int 모드로 BLOB을 엶

CLOB API

TbClob 클래스에서는 아래와 같은 API를 추가로 제공합니다.

API
설명

TbClob createEmptyClob()

EMPTY_CLOB을 생성하여 반환

void close()

CLOB을 닫음

int getBufferSize()

서버와 원활하게 통신할 수 있도록 32KB의 버퍼 크기를 반환

long getChars(long offset, char[]

buffer)

offset 위치부터 CLOB 데이터를 읽어서 buffer에 저장

long getChars(long offset, char[]

buffer, long numChars)

offset 위치부터 numChars만큼의 CLOB 데이터를 읽어서 buffer에 저장

long getChars(long offset, char[] buffer,

long bufOffset, long numChars)

offset 위치부터 numChars만큼의 CLOB 데이터를 읽어서 buffer의 bufOffset 위치에 저장

void open(int)

int 모드로 CLOB을 오픈

long putChars(long offset, char[] buffer)

buffer 데이터를 읽어서 offset 위치에 저장

long putChars(long offset, char[]

buffer, long numChars)

buffer 데이터를 numChars만큼 읽어서 offset 위치에 저장

long putChars(long offset, char[] buffer,

long bufOffset, long numChars)

buffer 데이터를 bufOffset 위치부터 numChars만큼 읽어서 offset 위치에 저장

NCLOB API

TbNClob 클래스에서는 아래와 같은 API를 추가로 제공합니다.

API
설명

TbNClob createEmptyNClob()

EMPTY_NCLOB을 생성하여 반환

void close()

NCLOB을 닫음

int getBufferSize()

서버와 원활하게 통신할 수 있도록 32KB의 버퍼 크기를 반환

long getChars(long offset, char[] buffer)

offset 위치부터 NCLOB 데이터를 읽어서 buffer에 저장

long getChars(long offset, char[] buffer, long numChars)

offset 위치부터 numChars만큼의 NCLOB 데이터를 읽어서 buffer에 저장

long getChars(long offset, char[] buffer, long bufOffset, long num Chars)

offset 위치부터 numChars만큼의 NCLOB 데이터를 읽어서 buffer의 bufOffset 위치에 저장

void open(int)

int 모드로 NCLOB을 오픈

long putChars(long offset, char[] buffer)

buffer 데이터를 읽어서 offset 위치에 저장

long putChars(long offset, char[] buffer, long numChars)

buffer 데이터를 numChars만큼 읽어서 offset 위치에 저장

long putChars(long offset, char[] buffer, long bufOffset, long num Chars)

buffer 데이터를 bufOffset 위치부터 numChars만큼 읽어서 offset 위치에 저장

Last updated