带有自定义绑定的 JOOQ 批量插入
Posted
技术标签:
【中文标题】带有自定义绑定的 JOOQ 批量插入【英文标题】:JOOQ Batch Insert with Custom Binding 【发布时间】:2021-09-08 09:27:33 【问题描述】:我正在尝试在批量插入的上下文中使用 JOOQ 流式传输 BLOB 参数。根据stream contents of 1GB file to sqlite table under single column,数据类型绑定是流式传输参数参数的方式。按照它的例子,我实现了 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 使用绑定的 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 的了解还不够多。
【问题讨论】:
【参考方案1】:JOOQ 调用转换器来处理初始值——即提供给values(null, null, null)
的初始参数,而不是提供给bind(obj1, obj2, ...)
的绑定变量。因此,只需传递这些 null 值,它就会起作用:
@Override
public KitItem from(byte[] databaseObject)
if (databaseObject == null)
return null;
throw new UnsupportedOperationException("Conversion should be streamed instead");
其次,不要尝试执行空批处理。在尝试使用 JOOQ 执行批处理语句之前,请检查您要插入的数据是否为空。如果尝试执行一个空批处理,初始值(通常为 null)将作为单个插入查询执行。
【讨论】:
以上是关于带有自定义绑定的 JOOQ 批量插入的主要内容,如果未能解决你的问题,请参考以下文章