![](/img/trans.png)
[英]How to upload file to Oracle DB as Blob/Clob using Helidon SE REST Services
[英]How to write large raw XML file to Oracle db using Blob object?
我有一個函數,可以使用FileInputStream
將大型XML文件轉換為字節數組。 它在我的IDE中運行良好,但是在通過可執行jar
獨立運行時,會Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
引發Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
。 我正在讀取字節數組中的大文件,以將其作為Blob存儲在目標數據庫中。 我無法控制Blob的存儲方式,我只能訪問存儲過程以插入Blob。 有沒有辦法在不將整個文件加載到內存的情況下讀寫數據塊?
將文件轉換為字節數組的函數-
private byte[] getBytesFromFile(Path path) throws IOException {
FileInputStream fis = new FileInputStream(path.toFile());
byte[] bytes = new byte[(int) path.toFile().length()];
int read = 0;
int offset = 0;
while(offset < bytes.length && (read = fis.read(bytes, offset, bytes.length - offset)) >= 0 ){
offset += read;
}
fis.close();
return bytes;
}
這是使用存儲過程調用將字節數組存儲到db的代碼
private void storeFileToDb(Connection connection, int fileId, String fileName, String fileType, byte[] fileBytes) throws SQLException {
//
String storedProcedure = "{call SP(?,?,?,?,?) }";
CallableStatement callableStatement = connection.prepareCall(storedProcedure);
callableStatement.setInt(1, fileId);
callableStatement.setString(2, fileName);
callableStatement.setString(3, fileType);
Blob fileBlob = connection.createBlob();
fileBlob.setBytes(1, fileBytes);
callableStatement.setBlob(4, fileBlob);
callableStatement.registerOutParameter(5, OracleTypes.NUMBER);
callableStatement.execute();
fileBlob.free(); // not entirely sure how this helps
//callableStatement.close();
}
使用CallableStatement.setBlob(int, InputStream)
或Blob.setBinaryStream(long)
。 兩種方法都可以使用InputStream
或OutputStream
對象,並避免在內存中創建byte[]
數組。 向數據庫文檔添加大型對象類型對象中顯示了示例。
只要JDBC驅動程序足夠聰明,不要在內部某個地方為整個blob創建byte[]
,它就應該起作用。
服務器配置可能太嚴格。 現在是檢查內存參數的好時機。
只需提供InputStream即可填充Blob。
壓縮XML數據也是一個好主意。 嘗試一下:將一些test.xml
壓縮為test.xml.gz
以獲得大小。
請注意,標准Java中存在:
private byte[] getBytesFromFile(Path path) throws IOException {
return Files.readAllBytes(path);
}
所以:
private void storeFileToDb(Connection connection, int fileId, String fileName,
String fileType) throws SQLException, IOException {
Path path = Paths.get(fileName); // Or parameter
try (CallableStatement callableStatement = connection.prepareCall(storedProcedure);
GZipInputStream fileIn = new GZipInputStream(Files.newBufferedInputStream(path))) {
...
callableStatement.setBlob(4, fileIn);
...
}
}
try-with-resources確保在引發異常或返回等情況下關閉。 對於聲明也很有用。
您沒有關閉語句,內部沒有Blob。 這是不可取的,因為數據可能會停留一段時間。 CallableStatement也是PreparedStatement,其中一個用例正在使用可能的其他參數值重復執行SQL。 或不。
並解壓縮GZipOutputStream
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.