[Oracle] JDBCによるLOBの操作方法 | Archive Redo Blog

Archive Redo Blog

DBエンジニアのあれこれ備忘録

JavaからLOBを操作するには、Oracle JDBCドライバに含まれるoracle.sql.BLOBクラス、またはoracle.sql.CLOBクラスを使用します。

これらのクラスはLOBロケータを保持し、LOB値の読み込み、書き込みを行うためのメソッドを提供しています。

oracle.sql.BLOBクラス、oracle.sql.CLOBクラスを使用したLOBの操作例を以下に示します。
BLOBデータの読み込み
BLOBデータを読み込むには、まずSELECT文を実行してBLOBロケータを取得します。

そして取得したBLOBロケータから入力ストリームを生成し、そこからBLOBデータを読み込んでいきます。

PreparedStatement pstmt 
  = conn.prepareStatement( 'SELECT BLOB_VALUE FROM TABLEA WHERE ID = ?' );
pstmt.setInt( 1, 1 );
rs = pstmt.executeQuery();
if( rs.next() ){
  BLOB blob = (( OracleResultSet ) rs ).getBLOB( 1 );
  InputStream ins = blob.getBinaryStream();
  bos = new ByteArrayOutputStream();
  int len = -1;
  byte[] buffer = new byte[ 8192 ];
  while( ( len = ins.read( buffer ) ) != -1 ){
    bos.write( buffer, 0, len );
  }
  blobValue = bos.toByteArray();
}

BLOBデータの書き込み
BLOBデータを書き込むには、まずSELECT文(FOR UPDATE付き)を実行してBLOBロケータを取得します。

そして取得したBLOBロケータから出力ストリームを生成し、そこへBLOBデータを書き込んでいきます。

ByteArrayOutputStream bos = ・・・
PreparedStatement pstmt 
  = conn.prepareStatement( 'SELECT BLOB_VALUE FROM TABLEA WHERE ID = ?'
    , ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE );
pstmt.setInt( 1, 1 );
rs = pstmt.executeQuery();
if( rs.next() ){
  BLOB blob = (( OracleResultSet ) rs ).getBLOB( 1 );
  OutputStream os = blob.getBinaryOutputStream();
  os.write( bos.toByteArray() );
}

CLOBデータの読み込み
CLOBデータを読み込むには、まずSELECT文を実行してCLOBロケータを取得します。

そして取得したCLOBロケータから入力ストリームを生成し、そこからCLOBデータを読み込んでいきます。

PreparedStatement pstmt 
  = conn.prepareStatement( 'SELECT CLOB_VALUE FROM TABLE_A WHERE ID = ?' );
pstmt.setInt( 1, 1 );
rs = pstmt.executeQuery();
if( rs.next() ){
  CLOB clob = (( OracleResultSet ) rs ).getCLOB( 1 );
  Reader reader = clob.getCharacterStream();
  int size = clob.getBufferSize();
  char[] cbuffer = new char[size];
  int length = -1;
  while ( ( length = reader.read( cbuffer ) ) != -1 )
  clobValue = cbuffer.toString();
}

CLOBデータの書き込み
CLOBデータを書き込むには、まずSELECT文(FOR UPDATE付き)を実行してCLOBロケータを取得します。

そして取得したCLOBロケータから出力ストリームを生成し、そこへCLOBデータを書き込んでいきます。

String clobValue = ・・・
PreparedStatement pstmt 
  = conn.prepareStatement( 'SELECT CLOB_VALUE FROM TABLE_A WHERE ID = ?'
  , ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE );
pstmt.setInt( 1, 1 );
rs = pstmt.executeQuery();
if( rs.next() ){
  clob = (( OracleResultSet ) rs ).getCLOB( 1 );
  writer = clob.getCharacterOutputStream();
  writer.write( clobValue );
  writer.close();
}

と、こんな感じですが、いずれの場合もLOBロケータを取得し、LOBロケータに対するストリームを生成し、読み書きを行うという手順になっています。

そのため、JDBCドライバを使いながら、Oracle依存のコーディングとなってしまうのが難点です。

使用するRDBMSがOracleオンリーであれば問題ないですが、マルチRDBMS対応のアプリケーションを作成する場合、RDBMS間の差異を吸収・隠蔽するためにどうしても一工夫必要になってしまいます。

なんとかならないものですかね...



【関連エントリ】
[Oracle] LOBデータの基本的な扱い方 2004/12/03
[Oracle] JDBCによるLOBの操作方法 2004/12/06
[Oracle] LOBデータをファイルから直接登録する方法(その1) 2005/01/25
[Oracle] LOBデータをファイルから直接登録する方法(その2) 2005/01/27
[Oracle] LOBデータをファイルに直接出力する方法 2005/02/01
[Oracle] JavaでLOBデータを読み込む際の最適なバッファサイズは? 2005/02/02
[Oracle] LOB記憶特性 その1(STORAGE IN ROW) 2005/08/23
[Oracle] LOB記憶特性 その2(CHUNK) 2005/08/24