簡體   English   中英

如何使用Blob對象將大型原始XML文件寫入Oracle數據庫?

[英]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) 兩種方法都可以使用InputStreamOutputStream對象,並避免在內存中創建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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM