8.5. ラージオブジェクトの使用

Postgresでは、(BLOBとしても知られる)ラージオブジェクトが、普通のSQLテーブルでは保存できないデータをデータベースに保存するために使われます。これらは特別なフォーマットでテーブルとは別に格納されて、テーブルからはOID値で参照されます。

Important: Postgresでは、ラージオブジェクトにアクセスするにはSQLのトランザクション内であることが必要です。パラメータをfalseとしてsetAutoCommit()を使うことで、トランザクションを開きます:

Connection mycon;
...
mycon.setAutoCommit(false);
... // now use Large Objects

ラージオブジェクトを使うには2つの方法があります。1番目は、標準JDBCによる方法で、ここに記載します。もう1つの方法はこのドライバ独自のAPIを拡張したものを使用します。これはlibpqでのラージオブジェクトAPIをJavaで表現したもので、標準のものよりもより優れたラージオブジェクトへのアクセス手段を提供します。ドライバの内部では、この拡張を使用してラージオブジェクトのサポートを提供しています。

JDBCでのラージオブジェクトにアクセスする標準的な方法はResultSetgetBinaryStream()メソッドとPreparedStatementsetBinaryStream()メソッドを使用することです。これらのメソッドはラージオブジェクトをJavaのストリームとして表現しますので、java.ioパッケージなどを使用してラージオブジェクトを扱うことができるようになります。Example 8-2は、この使用方法を示します。

Example 8-2. JDBCのラージオブジェクトインタフェースの使用

例えば、次のように画像のファイル名と画像用のラージオブジェクトから成るテーブルがあるとします:

CREATE TABLE images (imgname text, imgoid oid);

画像を挿入する場合、次のようになります:

File file = new File("myimage.gif");
FileInputStream fis = new FileInputStream(file);
PreparedStatement ps = conn.prepareStatement("INSERT INTO images VALUES (?, ?)"); (1)
ps.setString(1, file.getName());
ps.setBinaryStream(2, fis, file.length());
ps.executeUpdate();
ps.close();
fis.close();
(1)
?記号は次の行によって実際のデータに置換されます。
ここで、setBinaryStreamはストリーム経由でラージオブジェクトに設定されたバイト数分を転送し、その参照を保持するフィールドにそのOIDを保存します。データベースでラージオブジェクトの作成が透過的に成されることを知ってください。

画像を取り出すことはもっと簡単です。(ここではPreparedStatementを使っていますが、Statementでも同様に使うことができます。)

PreparedStatement ps = con.prepareStatement("SELECT oid FROM images WHERE name=?");
ps.setString(1, "myimage.gif");
ResultSet rs = ps.executeQuery();
if (rs != null) {
    while(rs.next()) {
        InputStream is = rs.getBinaryInputStream(1);
        // use the stream in some way here
        is.close();
    }
    rs.close();
}
ps.close();

ここでは、ラージオブジェクトがInputStreamとして取り出されていることが判るでしょう。結果の次の行を処理する前に、このストリームを閉じていることにも注意して下さい。これは、ResultSet.next()またはResultSet.close()が呼び出される時に全てのInputStreamから返される状態は閉ざされるというJDBC仕様の一部です。