带有自定义绑定的 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)将作为单个插入查询执行。
我正在尝试在批量插入的上下文中使用 JOOQ 流式传输 BLOB 参数。根据
@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)将作为单个插入查询执行。