带有自定义绑定的 JOOQ 批量插入

JOOQ Batch Insert with Custom Binding

我正在尝试在批量插入的上下文中使用 JOOQ 流式传输 BLOB 参数。根据 ,数据类型绑定是流式传输参数参数的方式。按照它的例子,我实现了 Binding#set:

    @Override
    public void set(BindingSetStatementContext<KitItem> ctx) throws SQLException {
        PreparedStatement statement = ctx.statement();
        Blob blob = statement.getConnection().createBlob();
        KitItem item = ctx.value(); // The object to write to the stream

        try (OutputStream output = blob.setBinaryStream(1)) {
            // Main serialization implementation
        } catch (IOException ex) {
            throw rethrow(ex);
        }
        statement.setBlob(ctx.index(), blob);
        ctx.autoFree(blob);
    }

这适用于简单的插入查询。但是,当我使用批量插入时,JOOQ 使用 Binding 的 Converter#from。我已经实现了 Converter#from 以抛出 UnsupportedOperationException。

        DataType<KitItem> itemType = KITPVP_KITS_CONTENTS.ITEM.getDataType().asConvertedDataType(new KitItemBinding());
        Field<KitItem> itemColumn = DSL.field(KITPVP_KITS_CONTENTS.ITEM.getQualifiedName(), itemType);
        if (true) { // Flipping this flag causes the Converter to be used
            for (ItemInSlot itemInSlot : contents) {
                context.insertInto(KITPVP_KITS_CONTENTS)
                        .columns(KITPVP_KITS_CONTENTS.KIT_ID, KITPVP_KITS_CONTENTS.SLOT, itemColumn)
                        .values(kitId, (byte) itemInSlot.slot(), itemInSlot.item())
                        .execute();
            }
        } else {
            BatchBindStep batch = context.batch(context
                    .insertInto(KITPVP_KITS_CONTENTS)
                    .columns(KITPVP_KITS_CONTENTS.KIT_ID, KITPVP_KITS_CONTENTS.SLOT, itemColumn)
                    .values((Field<Integer>) null, null, null));
            for (ItemInSlot itemInSlot : contents) {
                batch.bind(
                        kitId, itemInSlot.slot(), itemInSlot.item());
            }
            batch.execute();
        }

我怀疑这是我使用 JOOQ 的错误,因为我希望在设置参数时调用 Converter#to,而不是 Converter#from。即:

@Override
public KitItem from(byte[] databaseObject) {
    // I DO NOT expect this method to be called when setting parameters
    throw new UnsupportedOperationException("Conversion should be streamed instead");
}

@Override
public byte[] to(KitItem userObject) {
    // I expect this method or Binding#set to be called when setting parameters
    throw new UnsupportedOperationException("Conversion should be streamed instead");
}

我不确定这是否可能与 Jooq batch insert with custom field binding 有关,但我已经检查过这个问题(也没有答案)。这两种行为都可能是由 JOOQ 中的某些实现错误引起的。我对JOOQ的了解还不够多。

JOOQ 调用转换器来处理初始值——即提供给 values(null, null, null) 的初始参数,而不是提供给 bind(obj1, obj2, ...) 的绑定变量。因此,只需传递这些空值,它就会起作用:

@Override
public KitItem from(byte[] databaseObject) {
    if (databaseObject == null) {
      return null;
    }
    throw new UnsupportedOperationException("Conversion should be streamed instead");
}

其次,不要尝试执行空批处理。在尝试使用 JOOQ 执行批处理语句之前,请检查您要插入的数据是否为空。如果尝试执行一个空批处理,初始值(通常为 null)将作为单个插入查询执行。