【问题标题】:Jooq binding for "timestamp with time zone" type in postgresPostgres中“带有时区的时间戳”类型的Jooq绑定
【发布时间】:2016-01-15 09:43:22
【问题描述】:

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>

【问题讨论】:

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


    【解决方案1】:

    一种方法是使用反斜杠转义&lt;types&gt; 中的空格,如下所示:

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

    您不能只在 &lt;types&gt; 中使用常规空格,因为默认情况下,org.jooq.util.AbstractDatabaseparse regular expressions in COMMENTS mode 这使得创建的 Pattern 对象 ignore whitespace 在您的正则表达式中。您也可以执行&lt;types&gt;timestamp.*zone&lt;/types&gt; 之类的操作,或指定您自己的&lt;regexFlags&gt;

    以下是适用于我的完整 Maven jooq-codegen-maven 插件标签。我还发现&lt;binding&gt; 是不必要的。

    <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>
    

    【讨论】:

    • 其实现在想想,还是挺不直观的:手册里只提到了“Java regex”。无论如何,感谢您的精彩挖掘!
    • @assylias 不客气。配置的这方面绝对是不直观的,并且没有充分记录。我通过一些尝试和错误得到了答案,然后在事后找出了原因。
    • 这确实很不幸,而且没有必要。修复途中(希望):github.com/jOOQ/jOOQ/issues/4691
    • @LukasEder 在我的挖掘过程中,我遇到了 GitHub 问题,为什么要引入 COMMENTS 标志。我在您刚刚创建的新问题中注意到了这一点。
    【解决方案2】:

    当启用javaTimeTypes 时,Jooq 3.11 似乎将TIMESTAMP WITH TIME ZONE 转换为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'
        }
    }
    

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-05
      • 2019-11-08
      • 2020-09-19
      • 2015-05-06
      • 1970-01-01
      • 2015-03-03
      • 2022-11-22
      • 2021-06-25
      相关资源
      最近更新 更多