Java JOOq:通用表的更新

Java JOOq:通用表的更新,java,generics,casting,jooq,Java,Generics,Casting,Jooq,我想用JOOq创建一个通用的方法,该方法使用JSON对象中的值更新一个表(由字符串指定)。在这个示例中,我没有包括任何表/字段的验证 公共void updateTable(字符串表、JsonObject数据){ Table=PUBLIC.getTable(Table); UpdateSetFirstStep update=DSL.using(fooConfig).update(table); //循环JSON{field1:value1,field2:value2,…} for(Map.Entr

我想用JOOq创建一个通用的方法,该方法使用JSON对象中的值更新一个表(由字符串指定)。在这个示例中,我没有包括任何表/字段的验证

公共void updateTable(字符串表、JsonObject数据){
Table=PUBLIC.getTable(Table);
UpdateSetFirstStep update=DSL.using(fooConfig).update(table);
//循环JSON{field1:value1,field2:value2,…}
for(Map.Entry:数据){
String fieldName=entry.getKey();
字段=表字段(字段名);
对象值=entry.getValue();
//错误:未找到适用于集合的方法(字段,CAP#2)
update.set(field,field.getType().cast(value));
}
}
但是我得到了一个编译时错误:
没有为set(Field,CAP#2)找到合适的方法。

我认为问题在于编译器不知道字段的类型和值的类型是相同的(因此CAP#1和CAP#2)

有没有办法做到这一点

我认为问题在于编译器不知道字段的类型和值的类型是相同的(因此CAP#1和CAP#2)

这正是问题所在。同一通配符类型的两种不同用法会产生两种不同的新捕获类型

解决方案是引入一个小方法,其中通配符类型只使用一次并绑定到一个类型参数。当它绑定到一个类型参数时,编译器会识别出它的不同用法指向同一类型

像这样:

public void updateTable(String name, JsonObject data) {
    Table<?> table = PUBLIC.getTable(name);

    UpdateSetFirstStep<?> update = DSL.using(fooConfig).update(table);

    // Loop through JSON {field1: value1, field2: value2, ...}
    for (Map.Entry<String, Object> entry : data) {
        String fieldName = entry.getKey();
        Field<?> field = table.field(fieldName);

        Object value = entry.getValue();

        // Here the wildcard type is bound to the
        // type variable of the updateField method
        updateField(update, field, value);
    }
}

public <T> void updateField(UpdateSetStep<?> update, Field<T> field, Object value) {
    // When the wildcard is bound to T it can be used
    // multiple times without a problem
    update.set(field, field.getType().cast(value));
}

第三个有趣的解决方案 …将能够为
字段
声明一个本地类型变量:

<T> Field<T> field = table.field(fieldName);

最简单的解决方案是使用此方法。在为您进行数据类型转换时,它应用了相当宽松的类型安全性(如果可能):

公共void updateTable(字符串表、JsonObject数据){
Table=PUBLIC.getTable(Table);
DSL.using(fooConfig)
.更新(表格)
.set(data.entrySet()
.stream()
.map(e->new SimpleMultiTableEntry(table.field(e.getKey()),e.getValue())
.collect(Collectors.toMap(条目::getKey,条目::getValue)))
.where(…)//别忘了这个!;-)
.execute();
}
update.set(field, entry);
<T> Field<T> field = table.field(fieldName);
// Loop through JSON {field1: value1, field2: value2, ...}
for (Map.Entry<String, Object> entry : data) {
    String fieldName = entry.getKey();
    Field<?> field = table.field(fieldName);

    Object value = entry.getValue();

    captureType(field, f -> update.set(f, f.getType().cast(value)));
}

public static <T> void captureType(T o, Consumer<T> c) {
    c.accept(o);
}
Optional.of(field).ifPresent(f -> update.set(f, f.getType().cast(value)));
public void updateTable(String table, JsonObject data) {
    Table<?> table = PUBLIC.getTable(table);

    DSL.using(fooConfig)
       .update(table)
       .set(data.entrySet()
                .stream()
                .map(e -> new SimpleImmutableEntry(table.field(e.getKey()), e.getValue()))
                .collect(Collectors.toMap(Entry::getKey, Entry::getValue)))
       .where(...) // Don't forget this! ;-)
       .execute();
}