为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

莫回无 2023-03-23 16:42:35
我有一个函数可以使用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();}
查看完整描述

2 回答

?
12345678_0001

TA贡献1802条经验 获得超5个赞

使用CallableStatement.setBlob(int, InputStream)或 Blob.setBinaryStream(long)。这两种方法都可以使用InputStreamorOutputStream对象并避免byte[]在内存中创建数组。示例显示在将大对象类型对象添加到数据库文档中

只要 JDBC 驱动程序足够智能,不会byte[]在内部某处为整个 blob 创建,这就应该可以工作。



查看完整回答
反对 回复 2023-03-23
?
白板的微信

TA贡献1883条经验 获得超3个赞

可能是服务器配置过于严格。现在是检查内存参数的好时机。


只需提供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。


查看完整回答
反对 回复 2023-03-23
  • 2 回答
  • 0 关注
  • 132 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信