如何在不获取序列号的情况下使用jooq批量插入 预取所有序列值不使用记录

问题描述

我想使用jooq批量插入postgres:

List<MyTableRecord> records = new ArrayList<>();
for (Dto dto : dtos) {
    Field<Long> sequenceId = SEQUENCE.nextval();
    Long id = using(ctx).select(sequenceId).fetchOne(sequenceId);
    records.add(mapToRecord(dto,id));
}
using(ctx).batchInsert(records).execute();

问题是我要为每一行获取一个序列号。

对于简单的插入,我可以在语句中使用Field:

create.insertInto(ID,VALUE)
  .values(SEQUENCE.nextval(),val("William"))
  .execute();

如何批量插入呢?

解决方法

预取所有序列值

您可以使用以下方法预取所需的所有序列值:

List<Long> ids = using(ctx)
    .select(sequenceId)
    .from(generateSeries(1,dtos.size()))
    .fetch(sequenceId);

for (int i = 0; i < dtos.size(); i++)
    records.add(mapToRecord(dtos.get(i),ids.get(i)));

using(ctx).batchInsert(records).execute();

这似乎是一个有用的功能,可以通过using(ctx).nextvals(SEQUENCE,dtos.size())以RDBMS不可知的方式使用。我们将在以后的jOOQ版本中考虑这一点:https://github.com/jOOQ/jOOQ/issues/10658

不使用记录

一种替代方法是批处理实际的INSERT语句,而不是通过Record.insert()进行batchInsert()调用。这样,您可以将SEQUENCE.nextval()表达式放入语句中。参见:https://www.jooq.org/doc/latest/manual/sql-execution/batch-execution/