使用 jOOQ 更新 Postgres 日期范围

Update a Postgres daterange with jOOQ

我尝试更新 Postgres daterange。无论我尝试什么都行不通。目前我得到

Error:(51, 17) java: reference to set is ambiguous both method set(org.jooq.Field,T) in org.jooq.UpdateSetStep and method set(org.jooq.Field,org.jooq.Field) in org.jooq.UpdateSetStep match

这是我的代码

    ctx.update(AT_PREFERENCS)
            .set(AT_PREFERENCS.DIRECTION, preferences.direction)
            .set(AT_PREFERENCS.START_END, (Field<Object>) DSL.field("daterange(?, ?)", Object.class, preferences.start, preferences.end))
            .where(AT_PREFERENCS.USER.eq(userId))
            .execute(); 

如何使用 jOOQ 更新 daterange

这是由于非常不幸的 Java 语言设计问题(在我看来是一个主要缺陷)documented in this question here。 jOOQ 应该已经解决了这个问题,但是考虑到 jOOQ 早于 Java 8 并且在 Java 8 中引入了语言设计回归,这不能在 jOOQ API 中轻松修复并且向后兼容现在。

有几种解决方法:

创建数据类型绑定

如果您计划更频繁地使用此范围类型,这可能是最可靠的解决方案,在这种情况下您应该定义 custom data type binding。前面需要做一些额外的工作,但是一旦你指定了它,你就可以写:

.set(AT_PREFERENCES.START_END, new MyRangeType(preferences.start, preferences.end))

其中 AT_PREFERENCES.START_END 将是 Field<MyRangeType>

转换为原始类型并绑定一个未检查的显式类型变量,该变量不是 Object

如果您只使用这种类型一两次,这是一个快速的解决方法。它对 运行 时间没有影响,只是调整编译器使其相信这是正确的。

.<Void>set(
    (Field) AT_PREFERENCES.START_END, 
    (Field) DSL.field("daterange(?, ?)", Object.class, preferences.start, preferences.end))

转换为原始类型,然后返回到其他一些 Field<T> 类型

和以前一样,但是这让类型推断完成了为 <T>

推断 <Void> 的工作
.set(
    (Field<Void>) (Field) AT_PREFERENCES.START_END, 
    (Field<Void>) (Field) DSL.field("daterange(?, ?)", Object.class, 
                            preferences.start, preferences.end))

显式绑定到 "wrong" API 方法

jOOQ 在极少数情况下会在内部处理所有方法调用,这些情况会导致类型安全中断并调用 "wrong" 重载。因此,您也可以简单地调用它:

.set(
    AT_PREFERENCES.START_END, 
    (Object) DSL.field("daterange(?, ?)", Object.class, 
      preferences.start, preferences.end))

使用此转换,只有 set(Field<T>, T) 方法适用,您不再依赖 Java 编译器在适用的重载 (which no longer works since Java 8) 中找到最具体的方法。

jOOQ 将 运行 对 T 参数进行 instanceof 检查,看它是否真的是 Field 类型,如果它在内部重新通往预期 API 方法的路线 set(Field<T>, Field<T>)