Java 试图将BLOB作为InputStream读取,但连接关闭时出错。Spring3 getJdbcTemplate()

Java 试图将BLOB作为InputStream读取,但连接关闭时出错。Spring3 getJdbcTemplate(),java,spring,jdbc,spring-3,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

我正在移动一个应用程序以使用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();

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

最简单的解决方案是在
行映射器中执行处理,例如:

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);
getJdbcTemplate(){
public void mapRow(ResultSet rs,int rowNum)引发SQLException{
OracleLobHandler=新的OracleLobHandler();
InputStream InputStream=lobHandler.getBlobAsBinaryStream(rs,“文件内容”);
ExlImporter导入器=新的ExlBOMImporter(inputStream);
进口商。过程();
}
},fileId);
如果您只想处理第一行,那么使用
ResultSetExtractor
而不是
RowMapper
另一种(可能更简单)防止Spring过早关闭连接的方法是在执行查询之前启动事务

这可以通过在代码中插入

session.beginTransaction();

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

根据
ResultSet::getBinaryStream
文档,该值可以以“块”的形式读取,这意味着如果您关闭连接,然后尝试从流中读取足够的字节,那么当需要下一个块但无法从数据库返回时,它将引发异常


或者,您可以尝试使用
ResultSet::getBytes
方法读取整个值,然后根据需要将其转换为InputStream(通过tearrayinputstream
实例化新的
)。

有意义。它是有效的。感谢关于ResultsTextRactor位的提示。我相信它也可以通过“@Transactional”注释实现,但我没有对此进行测试,并且可能也不希望在事务中运行整个方法来接收Blob结果。此外,事务性注释仅适用于公共方法调用,因此在这种情况下也可能非常不切实际。
session.beginTransaction();