我正在处理一个Java Spring服务,它从Oracle数据库中读取一个BLOB类型的字段。这个BLOB字段包含一个zip文件,我的服务应该在响应体中将这个文件返回给客户端。
我实现了以下代码:
public void datasetDownload(String id, HttpServletResponse response) throws SQLException, IOException {
try (Connection connection = dataSource.getConnection()) {
String sql = "SELECT CONTENT FROM MY_TABLE_NAME WHERE ID = ?";
try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
preparedStatement.setString(1, id);
try (ResultSet resultSet = preparedStatement.executeQuery()) {
if (resultSet.next()) {
Blob blob = resultSet.getBlob("CONTENT");
try (InputStream inputStream = blob.getBinaryStream();
OutputStream outputStream = response.getOutputStream()) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
deleteRecord(id, connection);
}
}
}
}
}
字符串
但是,当我调用此服务时,我遇到以下异常:
java.lang.OutOfMemoryError:Java堆空间
我怀疑这个问题是由于从Oracle数据库阅读整个blob到内存中引起的。为了解决这个问题,我想我需要以较小的块读取blob,以避免耗尽Java堆空间,但我不知道如何做到这一点。
谢谢您的帮助!
编辑:我尝试添加一些日志:
public void datasetDownload(String id, HttpServletResponse response) throws SQLException, IOException {
try (Connection connection = dataSource.getConnection()) {
String sql = "SELECT CONTENT FROM MY_TABLE_NAME WHERE ID = ?";
try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
preparedStatement.setString(1, id);
try (ResultSet resultSet = preparedStatement.executeQuery()) {
if (resultSet.next()) {
log.info("Start downloading the BLOB");
log.info("Total memory available: " + (int) (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " MB");
log.info("Max memory available: " + (int) (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " MB");
try (InputStream inputStream = resultSet.getBinaryStream("CONTENT");
OutputStream outputStream = response.getOutputStream()) {
byte[] buffer = new byte[1024 * 1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
log.info("Memory available: " + (int) (Runtime.getRuntime().freeMemory() / (1024 * 1024)) + " MB");
}
}
deleteRecord(id, connection);
log.info("BLOB download completed");
}
}
}
}
}
型
发生的事情是,我可以看到最后一个日志“BLOB下载完成”,然后我得到OutOfMemoryError。
此外,最后的可用内存日志是:可用内存:570 MB
编辑:实际上我找到了一个解决方案,我用ZipOutputStream压缩了blob,机器没有内存不足。但我还是不知道问题出在哪里
1条答案
按热度按时间nxowjjhe1#
错误发生在哪一行?使用resultSet.getBinaryStream(),您可以保存一些行,它应该使用更少的内存,因为它不会首先加载blob。