将1GB文件的内容流式传输到单列下的sqlite表

时间:2018-06-17 16:10:25

标签: java sql jdbc jooq clob

以下实现为1 GB大小和4 GB堆空间的文件提供Out of Memory Error。 Files.lines将返回一个流,但在运行Collectors.joining时会出现堆错误。

我们可以使用jooq和jdbc保留原始行分隔符来流式传输内存占用较少的文件吗?

innerHTML

错误 - >

catch()

2 个答案:

答案 0 :(得分:2)

jOOQ对CLOB数据类型的默认数据类型绑定将CLOB类型视为普通String,适用于中小型lobs。对于较大的lobs,JDBC API的流式版本将更合适。理想情况下,您可以创建自己的数据类型绑定,在其中优化流式写入操作: https://www.jooq.org/doc/latest/manual/code-generation/custom-data-type-bindings

例如:

class StreamingLobBinding implements Binding<String, File> {
    ...
    @Override
    public void set(BindingSetStatementContext<File> ctx) {
        // Ideally: register the input stream somewhere for explicit resource management
        ctx.statement()
           .setBinaryStream(ctx.index(), new FileInputStream(ctx.value()));
    }
}

然后,您可以将此绑定应用于您的列,并让代码生成器按上述链接中的说明进行选择,或者仅将其应用于单个用途:

DataType<File> fileType = COL2.getDataType().asConvertedDataType(new StreamingLobBinding());
Field<File> fileCol = DSL.field(COL2.getName(), fileType);
dsl.insertInto(TABLE1)
   .columns(COL1, fileCol)
   .values(VAL1, DSL.val(theFile, fileType))
   .execute();

请注意,目前,您可能需要在某些ThreadLocal中注册输入流以记住它并在语句执行后进行清理。未来的jOOQ版本将提供SPI来处理:https://github.com/jOOQ/jOOQ/issues/7591

答案 1 :(得分:2)

由于<chain>使用sqlite-jdbc抛出了SQLFeatureNotSupportedException,因此上述github问题中提出了另一种方法。

setBinaryStream