使用jOOQ更新Postgres日期范围

时间:2017-07-06 21:19:49

标签: java postgresql jooq

我尝试更新Postgres daterange。无论我尝试什么,它都不起作用。目前我得到

  

错误:(51,17)java:对set的引用是不明确的     org.jooq.UpdateSetStep中的方法集(org.jooq.Field,T)和org.jooq.UpdateSetStep中的方法集(org.jooq.Field,org.jooq.Field)匹配

这是我的代码

    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

1 个答案:

答案 0 :(得分:2)

这是由于非常不幸的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_ENDField<MyRangeType>

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

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

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

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

与之前相同,但是这样,类型推断可以为<Void>推断<T>

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

明确地绑定&#34;错误&#34; API方法

jOOQ内部处理所有方法调用,在极少数情况下,类型安全性中断并且&​​#34;错误&#34;调用过载。所以,您也可以简单地称之为:

.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将对instanceof参数运行T检查,看看它是否真的是Field类型,如果它在内部重新路由到预期的API方法set(Field<T>, Field<T>)