2012-03-23 19 views
3

私はSpring3フレームワークを使用するようにアプリケーションを動かしていると私は、OracleデータベースからBLOB列を読み取るコードを持っている:BLOBをInputStreamとして読み込み中にConnection Closedエラーが発生しました。 Spring3 getJdbcTemplate()

これは動作します:

 String fileSqlStr = 
       "select file_id, file_content from cpm_file where file_id = 4"; 
     PreparedStatement ps = conn.prepareStatement(fileSqlStr); 
     ResultSet rs = ps.executeQuery(); 
     rs.next(); 
     int fileId = rs.getInt("file_id"); 
     InputStream fis = rs.getBinaryStream("file_content"); 
     ExlBOMImporter ei = new ExlBOMImporter(fis); 

しかし、私は書き込みをしてみてくださいそれ春はJdbcTemplate豆を使用して:

InputStream is = getJdbcTemplate().query(getFileContentSql, new RowMapper<InputStream>() { 

       public InputStream mapRow(ResultSet rs, int rowNum) throws SQLException { 
        OracleLobHandler lobHandler = new OracleLobHandler(); 
        return lobHandler.getBlobAsBinaryStream(rs, "file_content"); 
       } 
      }, fileId).get(0); 
ExlImporter importer = new ExlBOMImporter(is); 
importer.process(); 

私はjava.io.IOException: Closed Connection例外を取得しています。

私は、処理する前に、SpringがInputStreamの接続を閉じる必要があると考えています。あなたたちはこれを書く良い方法がありますか?

編集:例外にいくつかのより多くの深さ:それはquery方法を離れるとき

java.io.IOException: Closed Connection 
     at oracle.jdbc.driver.OracleBlobInputStream.needBytes(OracleBlobInputStream.java:204) 
     at oracle.jdbc.driver.OracleBufferedStream.readInternal(OracleBufferedStream.java:169) 
     at oracle.jdbc.driver.OracleBufferedStream.read(OracleBufferedStream.java:143) 
     at org.apache.poi.util.IOUtils.readFully(IOUtils.java:92) 
     at org.apache.poi.util.IOUtils.readFully(IOUtils.java:77) 
     at oracle.jdbc.driver.OracleBlobInputStream.needBytes(OracleBlobInputStream.java:204) 

答えて

4

はい、春は接続を整理します。

最も簡単な解決策は、RowMapperの内部で処理を行うことです。

getJdbcTemplate().query(getFileContentSql, new RowMapper<Void>() { 
    public void mapRow(ResultSet rs, int rowNum) throws SQLException { 
     OracleLobHandler lobHandler = new OracleLobHandler(); 
     InputStream inputStream = lobHandler.getBlobAsBinaryStream(rs, "file_content"); 
     ExlImporter importer = new ExlBOMImporter(inputStream); 
     importer.process(); 
    } 
}, fileId); 

あなたが最初の行だけを処理したい場合は、代わりにRowMapperResultSetExtractorを使用しています。

+0

意味があります。そして、それは動作します。 ResultSetExtractorビットのヒントをありがとう。 – jonasespelita

0

Springが接続を途中で閉じるのを防ぐもう1つの(おそらく簡単な)方法は、クエリを実行する前にトランザクションを開始することです。

これはどこかのexecuteQueryの呼び出しの前に

session.beginTransaction(); 

を挿入することで、コード内で行うことができます。

+0

私はそれを '@ Transactional'アノテーションでも実現できると信じていますが、これをテストしていないし、ブロブ結果を受け取る唯一の目的のためにトランザクション内でメソッド全体を実行することもおそらく望ましくありません。 さらに、トランザクションアノテーションはパブリックメソッドコールでのみ機能するため、このような状況では非常に非実用的です。 –

0

ResultSet::getBinaryStreamドキュメントでは、値は「チャンク」で読み取ることができます。つまり、接続を閉じてからストリームから十分なバイト数を読み取ると、次のチャンクが必要なときに例外が発生します。データベースから戻すことはできません。

ResultSet::getBytesメソッドを使用して値全体を読み取ってから、新しいByteArrayInputStreamをインスタンス化する必要がある場合は、それをInputStreamに変換してみてください。

関連する問題