Java 试图将BLOB作为InputStream读取,但连接关闭时出错。Spring3 getJdbcTemplate()
我正在移动一个应用程序以使用Spring3框架,我有一段代码,可以从Oracle数据库中读取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
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();