猿问

如何使用 Blob 对象将大型原始 XML 文件写入 Oracle 数据库?

我有一个函数可以使用FileInputStream. 它在我的 IDE 中运行良好,但是当通过可执行文件独立运行时jar,它抛出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();

}


莫回无
浏览 170回答 2
2回答

12345678_0001

使用CallableStatement.setBlob(int, InputStream)或&nbsp;Blob.setBinaryStream(long)。这两种方法都可以使用InputStreamorOutputStream对象并避免byte[]在内存中创建数组。示例显示在将大对象类型对象添加到数据库文档中。只要 JDBC 驱动程序足够智能,不会byte[]在内部某处为整个 blob 创建,这就应该可以工作。

白板的微信

可能是服务器配置过于严格。现在是检查内存参数的好时机。只需提供InputStream即可填充 Blob 。压缩 XML 数据也是一个好主意。尝试一下:将一些压缩test.xml为test.xml.gz,以获得大小增益。注意标准java中存在:private byte[] getBytesFromFile(Path path) throws IOException {&nbsp; &nbsp; return Files.readAllBytes(path);}所以:private void storeFileToDb(Connection connection, int fileId, String fileName,&nbsp; &nbsp; &nbsp; &nbsp; String fileType) throws SQLException, IOException {&nbsp; &nbsp; Path path = Paths.get(fileName); // Or parameter&nbsp; &nbsp; try (CallableStatement callableStatement = connection.prepareCall(storedProcedure);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;GZipInputStream fileIn = new GZipInputStream(Files.newBufferedInputStream(path))) {&nbsp; &nbsp; &nbsp; &nbsp; ...&nbsp; &nbsp; &nbsp; &nbsp; callableStatement.setBlob(4, fileIn);&nbsp; &nbsp; &nbsp; &nbsp; ...&nbsp; &nbsp; }}try-with-resources 确保在抛出异常或返回等情况下关闭。对语句也很有用。您没有关闭语句,里面有一个 Blob。这是不可取的,因为数据可能会停留一段时间。CallableStatement 也是 PreparedStatement,其中一个用例使用可能的其他参数值重复执行 SQL。或不。并用于解压GZipOutputStream。
随时随地看视频慕课网APP

相关分类

Java
我要回答