Jooq在Postgres中绑定"timestamp with time zone"类型

5

Jooq目前不支持JSR 310类型支持将在v3.8之后才会到来

通常使用简单的转换器是可行的,但对于某些类型,例如postgres的TIMESTAMP WITH TIME ZONE,需要自定义绑定。因此,我尝试编写了一个,但生成的XxxRecord类仍然在我的DB中的TIMESTAMP WITH TIME ZONE字段中使用Timestamp数据类型。

我需要更改下面的代码以在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个回答

7

一种方法是使用反斜杠转义<types>中的空格,如下所示:

<types>timestamp\ with\ time\ zone</types>

<types>中不能只使用普通空格,因为默认情况下,org.jooq.util.AbstractDatabase解析注释模式的正则表达式,这会使得创建的Pattern对象忽略正则表达式中的空格。您还可以像这样做:<types>timestamp.*zone</types>,或指定自己的<regexFlags>

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

<plugin>
    <groupId>org.jooq</groupId>
    <artifactId>jooq-codegen-maven</artifactId>
    <version>3.7.0</version>

    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
        </execution>
    </executions>

    <configuration>

        <jdbc>
            <driver>org.postgresql.Driver</driver>
            <url>jdbc:postgresql:postgres</url>
            <user>postgres</user>
            <password>mypass</password>
        </jdbc>

        <generator>
            <database>
                <customTypes>
                    <customType>
                        <name>Instant</name>
                        <type>java.time.Instant</type>
                        <converter>xxx.TimestampConverter</converter>
                    </customType>
                </customTypes>

                <forcedTypes>
                    <forcedType>
                        <name>Instant</name>
                        <types>timestamp\ with\ time\ zone</types>
                    </forcedType>
                </forcedTypes>

                <name>org.jooq.util.postgres.PostgresDatabase</name>
                <includes>author</includes>
                <excludes/>
                <inputSchema>public</inputSchema>
            </database>
            <target>
                <packageName>xxx.table</packageName>
                <directory>target/generated-sources/jooq</directory>
            </target>
        </generator>
    </configuration>
</plugin>

1
现在想起来,其实很不直观:手册只提到了“Java正则表达式”。无论如何,感谢你的努力! - assylias
1
@assylias 不用谢。这个配置方面确实不直观,文档也不够详细。我通过一些试错得到了答案,然后在事后找到了解释原因的资料。 - heenenee
1
非常不幸,这是不必要的。修复正在进行中(希望如此):https://github.com/jOOQ/jOOQ/issues/4691 - Lukas Eder
@LukasEder 在我的调查过程中,我发现了关于为什么引入“COMMENTS”标志的GitHub问题。我在你刚创建的新问题中做了记录。 - heenenee

4
Jooq 3.11似乎在启用javaTimeTypes时将变成了OffsetDateTime,并且它还抱怨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'
    }
}

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接