postgres中的“带时区的时间戳”的Jooq绑定

时间:2015-10-16 15:09:57

标签: java postgresql java-8 jooq java-time

Jooq currently does not support JSR 310 typessupport will not come until v3.8

使用简单转换器通常可以工作,但某些类型除外,例如postgres'TIMESTAMP WITH TIME ZONE,它需要自定义绑定。所以我尝试编写一个,但生成的XxxRecord类仍然使用Timestamp数据类型作为我的数据库中的TIMESTAMP WITH TIME ZONE字段。

我需要在下面的代码中更改哪些内容,以便在jooq生成的类中将postgres'TIMESTAMP WITH TIME ZONE视为Instant

转换器

public class TimestampConverter implements Converter<Timestamp, Instant> {
  @Override public Instant from(Timestamp ts) {
    return ts == null ? null : ts.toInstant();
  }
  @Override public Timestamp to(Instant instant) {
    return instant == null ? null : Timestamp.from(instant);
  }
  @Override public Class<Timestamp> fromType() { return Timestamp.class; }
  @Override public Class<Instant> toType() { return Instant.class; }
}

自定义绑定

public class TimestampBinding implements Binding<Timestamp, Instant> {

  private static final Converter<Timestamp, Instant> converter = new TimestampConverter();

  private final DefaultBinding<Timestamp, Instant> delegate = 
                                                       new DefaultBinding<> (converter());

  @Override public Converter<Timestamp, Instant> converter() { return converter; }

  @Override public void sql(BindingSQLContext<Instant> ctx) throws SQLException {
    delegate.sql(ctx);
  }

  //etc. same for all other overriden methods.
}

pom.xml(摘录)

<customType>
  <name>java.time.Instant</name>
  <type>java.time.Instant</type>
  <binding>xxx.TimestampBinding</binding>
</customType>

...

<forcedType>
  <name>java.time.Instant</name>
  <types>timestamp with time zone</types>
</forcedType>

2 个答案:

答案 0 :(得分:5)

一种方法是使用反斜杠转义"netsh winsock reset catalog"中的空格,如下所示:

<types>

<types>timestamp\ with\ time\ zone</types> 您只能拥有常规空格,因为默认情况下,<types>parse regular expressions in COMMENTS mode生成org.jooq.util.AbstractDatabase对象ignore whitespace你的正则表达式。您也可以执行Pattern之类的操作,或指定自己的<regexFlags>

以下是适用于我的完整Maven <types>timestamp.*zone</types>插件标记。我还发现jooq-codegen-maven是不必要的。

<binding>

答案 1 :(得分:1)

Jooq 3.11似乎在启用TIMESTAMP WITH TIME ZONE时将OffsetDateTime变成了javaTimeTypes,并且它还抱怨customTypes被弃用,所以我无法得到其他答案为我工作。

这是我使用gradle jooq插件使它工作的方式:

// inside the jooq...generator.database of build.gradle:
forcedTypes {
    forcedType {
        userType = 'java.time.Instant'
        converter = '''
        org.jooq.Converter.ofNullable(
            java.time.OffsetDateTime.class,
            java.time.Instant.class,
            o -> o.toInstant(),
            i -> i.atOffset(java.time.ZoneOffset.UTC))
        '''
        types = 'timestamp\\ with\\ time\\ zone'
    }
}

将它转换为Maven或手动调用代码生成器的XML应该很容易,因为gradle插件的参数完全匹配XML的结构。请注意,Groovy语法要求types模式中的反斜杠加倍,因此在转换为XML时需要进行调整。

这使用内联转换器将Jooq当前使用的OffsetDateTime转换为Instant。不需要外部转换器类。