4

JBoss 4.2.3 AS で動作する EJB 3.0 と Hibernate を使用するアプリケーションと、EJB によって制御されるトランザクションがあります。

「エラー: 無効なラージ オブジェクト記述子: 0」や「エラー: ラージ オブジェクト 488450 が存在しません」などのラージ オブジェクトに関するいくつかのメッセージが Postgres ログに出力されるという問題に直面していました。その結果、アプリケーションではすべてが正常に機能しましたが、休止状態のコミット後 (メソッドと呼ばれるメイン EJB のすべてのコードが実行された後)、Postgres がトランザクションをコミットできない場合がありました (常にではありません)。

レガシ コードを調査したところ、データベース内のファイル ストレージを表すすべてのエンティティのスーパークラスが見つかりました。このクラスでは、ファイルは Blob 属性によって表され、getBinaryStream() メソッドによって使用されます。私が奇妙だと思ったのは、このクラスの finalize() メソッドにあるものです。

@Lob
@Basic(fetch = FetchType.LAZY)
@Column(name = "BIN_CONTENT", nullable = true, updatable = true)
protected Blob content;

@Override
protected void finalize() throws Throwable {
    if (this.content != null) {
        try {
            IOUtils.closeQuietly(this.content.getBinaryStream());
        } catch (Exception e) {
            logger.severe("Error finalizing Blob stream");
        }
        try {
            this.content.free();
        } catch (AbstractMethodError e) {
        } catch (SQLFeatureNotSupportedException e) {
        } catch (UnsupportedOperationException e) {
        } catch (Throwable e) {
            logger.severe("Error finalizing Blob stream");
        }
        this.content = null;
    }
    super.finalize();
}

このコードにコメントした後、すべてがうまくいくように見えました。質問は次のとおりです。それは必要ですか?データベース側でエラーを引き起こしているこのコードの実行により、内部で何が起こっているのかを理解したいと思います。

4

1 に答える 1

2

あなたが提供したコードにはいくつかの問題があります。

最初の問題はfinalize()タイミングです。

java.sql.Blob実装は jdbc ドライバーに依存し、通常、実装クラスは blob の識別子のみを格納し、コンテンツがアクセスされると (getBinaryStream()たとえば、データベースへの別の呼び出しが実行されます)。これgetBinaryStream()は、呼び出された時点で、blob の取得に使用された接続がまだ開かれている必要があることを意味します。ただし、JVM は、ファイナライズがいつ呼び出されるかを保証しないため、ファイナライズで Blob にアクセスすることは正しくありません。

PostgreSQL jdbc ドライバーがこのロジックを BLOB に使用するかどうかはわかりませんが、java.sql.Array実装にこの制限があることは確かです (つまり、接続が閉じられた後に配列のメソッドを呼び出すことはできません)。

2 番目の問題は、blob マッピングが遅延として定義されているにもかかわらず、クライアントがそれを使用していない場合でも、blob フィールドが常に によってロードされることfinalize()です。

一般に、BLOB を使用する場合、クリーンアップを実行するのはクライアントの責任です。BLOB の使用パターンは次のとおりです。

try {
    blob = entity.getContent();
    // ... use blob
} finally {
    // ... do blob cleanup
}
于 2013-10-27T09:31:39.647 に答える