8.3 JavaにおけるLOB用のデータ・インタフェース

この項では、JavaにおけるLOB用のデータ・インタフェースの使用方法について説明します。

CLOBおよびBLOBデータの読取りおよび書込みは、LONGデータおよびLONG RAWデータの場合と同じストリーミング・メカニズムを使用して行うことができます。

読取り操作には、SELECT文によって戻された永続LOBまたは一時LOBでdefineColumnType(nn, Types.LONGVARCHAR)メソッドまたはdefineColumnType(nn, Types.LONGVARBINARY)メソッドを使用します。これにより、VARCHAR2またはRAW列に類似したデータに直接ストリームが生成されます。

ノート:

  1. VARCHARまたはRAWdefineColumnTypeとして使用すると、選択した値は32kに切り捨てられます。
  2. ResultSetおよびCallableStatementgetStringgetBytesなどの標準JDBCメソッドは、その下のLOBロケータを使用するため、データ・インタフェースの一部ではありません。

文字データをPreparedStatementのLOB列に挿入するには、BLOBまたはCLOBであるパラメータにsetBinaryStream()setCharacterStream()またはsetAsciiStream()を使用できます。これらの方法では、ストリーム・インタフェースを使用して、ストリーム内のデータからデータベース内にLOBを作成します。データの長さが不明である場合は、プロジェクトを向上させるために、長さパラメータを受け入れるsetBinaryStream()またはsetCharacterStreamファンクションのバージョンを使用します。データ・インタフェースでは、LOBデータを書き込むために、PreparedStatementsetStringsetBytesなどの標準JDBCメソッドもサポートされています。これらのAPIをLOBアクセスに使用するためのコーディングが簡単になり、多くの場合は処理が高速化されます。これらの手法はすべて、データベース・ラウンドトリップを削減し、多くの場合にパフォーマンスを向上させます。

次のコード・スニペットは、すべてのJDBCドライバで機能します。

バインド:

非ストリーミング・モードの場合:

...
String sql = "insert into print_media (product_id, ad_id, ad_final_text)" +
             " values (:1, :2, :3)";
    PreparedStatement pstmt = conn.prepareStatement(sql);
    pstmt.setInt( 1, 2 );
    pstmt.setInt( 2, 20);
    pstmt.setString( 3, "Java string" );
    int rows = pstmt.executeUpdate();
...

ノート:

最大2 GBのサイズの文字列に対して非ストリーム・モードがサポートされていますが、マシンのメモリーが制限要因である可能性があります。

ストリーミング・モードの場合、前述と同じコードが機能しますが、setString()文は次のいずれかで置き換えられます。

pstmt.setCharacterStream( 3, new LabeledReader(), 1000000 );
pstmt.setAsciiStream( 3, new LabeledAsciiInputStream(), 1000000 );

ノート:

ストリーミング・インタフェースを使用して、ギガバイト・サイズの文字およびバイナリ・データをLOB列に挿入できます。

ここで、LabeledReader()およびLabeledAsciiInputStream()により、それぞれ文字ストリームおよびASCIIストリームが生成されます。ad_finaltextCLOBではなくBLOB列である場合、前述の例は、バインドがRAW型である場合に機能します。

pstmt.setBytes( 3, <some byte[] array> );
pstmt.setBinaryStream( 3, new LabeledInputStream(), 1000000 );

ここで、LabeledInputStream()によってバイナリ・ストリームが生成されます。

定義:

非ストリーミング・モードの場合:

OracleStatement stmt = (OracleStatement)(conn.createStatement());
  stmt.defineColumnType( 1, Types.VARCHAR );
  ResultSet rst = stmt.executeQuery("select ad_finaltext from print_media" );
  while( rst.next() )
     {
       String s = rst.getString( 1 );
       System.out.println( s );
     }

ノート:

LOBサイズが32767バイトより大きい場合、データは切り捨てられ、エラーはスローされません。

ストリーミング・モードの場合:

OracleStatement stmt = (OracleStatement)(conn.createStatement());
  stmt.defineColumnType( 1, Types.LONGVARCHAR );
  ResultSet rst = stmt.executeQuery("select ad_finaltext from print_media" );
  while(rs.next()) {  
    Reader reader = rs.getCharacterStream( 1 );  
    int data = 0;  
    data = reader.read();   
    while( -1 != data ){    
      System.out.print( (char)(data) );    
      data = reader.read();  
      }  
    reader.close();
    }

ノート:

データ型をLONGVARCHARとして指定すると、LOB全体を選択できます。定義タイプがLONGVARCHARではなくVARCHARに設定されている場合、データは32kで切り捨てられます。

ad_finaltextCLOBではなくBLOB列である場合、前述の例は、定義がLONGVARBINARY型である場合に機能します。

...
OracleStatement stmt = (OracleStatement)conn.createStatement();

stmt.defineColumnType( 1, Types.INTEGER );
stmt.defineColumnType( 2, Types.LONGVARBINARY );
 
ResultSet rset = stmt.executeQuery("SELECT ID, LOBCOL FROM LOBTAB");
	while(rset.next())
	{
     		/* using getBytes() */
     		/*
     		byte[] b = rset.getBytes("LOBCOL");
		System.out.println("ID: " + rset.getInt("ID") + "  length: " + b.length);
     		*/
 
	        /* using getBinaryStream() */
        	InputStream byte_stream = rset.getBinaryStream("LOBCOL");
        	byte [] b = new byte [100000];
	        int b_len = byte_stream.read(b);
        	System.out.println("ID: " + rset.getInt("ID") + "  length: " + b_len);
 
	        byte_stream.close();
    	}
...