我目前正在編寫一個Java應用程序來從數據庫中檢索BLOB
類型的數據,我使用查詢來獲取所有數據並將它們存儲在Map<String, Object>
的列中。當我需要使用數據時,我重複列表以獲取信息。Java OutOfMemoryError
但是,當我試圖獲取行列表超過幾次時,我得到了一個OutOfMemoryError
。我是否需要在代碼中釋放內存?我的代碼如下:
ByteArrayInputStream binaryStream = null;
OutputStream out = null;
try {
List<Map<String, Object>> result =
jdbcOperations.query(
sql,
new Object[] {id},
new RowMapper(){
public Object mapRow(ResultSet rs, int i) throws SQLException {
DefaultLobHandler lobHandler = new DefaultLobHandler();
Map<String, Object> results = new HashMap<String, Object>();
String fileName = rs.getString(ORIGINAL_FILE_NAME);
if (!StringUtils.isBlank(fileName)) {
results.put(ORIGINAL_FILE_NAME, fileName);
}
byte[] blobBytes = lobHandler.getBlobAsBytes(rs, "AttachedFile");
results.put(BLOB, blobBytes);
int entityID = rs.getInt(ENTITY_ID);
results.put(ENTITY_ID, entityID);
return results;
}
}
);
int count = 0;
for (Iterator<Map<String, Object>> iterator = result.iterator();
iterator.hasNext();)
{
count++;
Map<String, Object> row = iterator.next();
byte[] attachment = (byte[])row.get(BLOB);
final int entityID = (Integer)row.get(ENTITY_ID);
if(attachment != null) {
final String originalFilename = (String)row.get(ORIGINAL_FILE_NAME);
String stripFilename;
if (originalFilename.contains(":\\")) {
stripFilename = StringUtils.substringAfter(originalFilename, ":\\");
}
else {
stripFilename = originalFilename;
}
String filename = pathName + entityID + "\\"+ stripFilename;
boolean exist = (new File(filename)).exists();
iterator.remove(); // release the resource
if (!exist) {
binaryStream = new ByteArrayInputStream(attachment);
InputStream extractedStream = null;
try {
extractedStream = decompress(binaryStream);
final byte[] buf = IOUtils.toByteArray(extractedStream);
out = FileUtils.openOutputStream(new File(filename));
IOUtils.write(buf, out);
}
finally {
IOUtils.closeQuietly(extractedStream);
}
}
else {
continue;
}
}
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
finally {
IOUtils.closeQuietly(out);
IOUtils.closeQuietly(binaryStream);
}
這也是我的想法,因爲我不希望我的應用程序在另一臺計算機上運行時需要更改JVM設置。但是這樣我可能需要多次查詢數據庫,並且非常仔細地將結果分組以便不會錯過任何行。 – newguy
我修改了我的代碼和查詢,以便它基於一系列ID執行查詢,並且OutOfMemory再也不會發生。 – newguy
也許我錯過了一些東西,但是......我想你「只是」需要用一個將blob保存到磁盤的方法來調用「put()」代碼 - 寫入方法的第二部分。將其拆分成單獨的方法將使代碼更易於理解。然後你的mapRow()函數不必返回任何重要的東西 - 你不會使用返回值。 –