我正在移动一个应用程序来使用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)
答案 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
)。