在jOOQ中,如何按需获取、逐行处理并将结果以CSV格式输出?

后端开发 2026-07-10

I currently have code like this:

try (var cursor = query().fetchSize(1000).fetchLazy()) {
    cursor.formatCSV(out);
}

这正是我想要的——懒加载获取结果(我的结果量巨大,根本无法全部装入内存),并且正确地将其格式化为CSV。

然而,现在我需要以一种方式对记录进行预处理,使某些记录被拆分成很多条。

类似于:

try (var stream = query().fetchSize(1000).stream()) {
    stream
        .mapMulti(...) //split the records as needed
        .forEach(r -> r.formatCSV(out));
}

但这存在若干问题。首先,输出表头要么对每一行输出,要么根本不输出,取决于我传入的格式。此外,在记录上调用 formatCSV() 会先把记录包装在一个 Result 中,在我的场景里意味着为数千万个对象分配内存,几乎等于白费。

我该如何解决这些问题?

解决方案

首先,我将根据传入的格式要么对每一行打印表头,要么根本不打印表头。

把包含表头的格式仅用于第一条记录,或者基于 Cursor.fields() 创建一个不包含任何记录的假 Result,并打印该结果的表头。

在我的场景里,这意味着为几千万个对象分配内存,基本上等于白费。

你是否有任何基准测试来证明这确实会成为问题?Result 其实只是一个 ArrayList,在这种情况下每条记录只有一个元素。也许会更好,是的。但难道那么糟糕吗?逃逸分析也许会生效,你会没事。与正在发生的实际输入/输出相比,这点开销就不值一提……

另一种方法是把记录分块收集到你自己的 Result 实例中(例如每块100条),然后把每块整体导出为CSV。

如果这是一个显著的问题,为什么不提交一个 bug

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章