尝试将BLOB读取为InputStream但是出现Connection Closed错误。 Spring3 getJdbcTemplate()

时间:2012-03-23 12:47:15

标签: java spring jdbc spring-3

我正在移动一个应用程序来使用Spring3框架,我有从Oracle数据库中读取BLOB列的代码:

这有效:

        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);

但是当我尝试用Spring编写它时使用JdbcTemplate bean:

 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的连接。你们有更好的写作方式吗?

编辑:更多深度到例外:

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)

3 个答案:

答案 0 :(得分:4)

是的,Spring会在离开query方法时整理连接。

最简单的解决方案是在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);

如果您只想处理第一行,请使用ResultSetExtractor代替RowMapper

答案 1 :(得分:0)

另一种(可能更简单)阻止Spring过早关闭连接的方法是在执行查询之前启动事务。

这可以通过插入

在代码中完成
<div class="container">
  <div class="nowrap">This text should be truncated</span>
</div>

<div class="container two">
  <div class="nowrap">This text should be truncated</span>
</div>

在executeQuery调用之前的某个地方。

答案 2 :(得分:0)

根据ResultSet::getBinaryStream文档,可以在“块”中读取值,这意味着如果关闭连接然后尝试从流中读取足够的字节,则在下一个块时会引发异常需要但不能从数据库返回。

作为替代方法,您可以尝试使用ResultSet::getBytes方法读取整个值,然后在需要时将其转换为InputStream(实例化新的ByteArrayInputStream)。