繁体   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