![](/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.