在jOOQ中我们如何使用Java Instant映射到Postgresql的时间戳类型?

问题描述 投票:0回答:2

我相当惊讶地发现 jOOQ(截至 3.16)将时间戳绑定到

LocalDateTime
。 在我看来,时间戳最自然地映射到
Instant
,它是 Unix 纪元时间戳。

那么我们如何让 jOOQ 生成使用

Instant
而不是
LocalDateTime
的代码呢? 我需要使用力发生器吗?

我尝试使用像这样的强制类型,但它永远不会选择我的强制类型。

.withForcedTypes(
    new ForcedType()
        .withUserType(Instant.class.getCanonicalName())
        .withConverter(com.monsolei.data.InstantConverter.class.toString())
        .withIncludeExpression("timestamp")
)
jooq jooq-codegen-maven
2个回答
4
投票

关于 PostgreSQL 时间戳数据类型

在 PostgreSQL 中(我假设您使用的是 PG),

TIMESTAMP
TIMESTAMP WITHOUT TIME ZONE
的缩写,如下所述:https://www.postgresql.org/docs/current/datatype-datetime.html

将其映射到的最佳 Java 类型是:

  • java.sql.Timestamp
    (旧的 JDBC 类型,其
    valueOf()
    toString()
    行为不支持时区,但也适用于您当地的时区)
  • java.time.LocalDateTime

您也可以在 JDBC 规范中看到这一点,或者从存在诸如

java.sql.Timestamp.valueOf(LocalDateTime)
java.sql.Timestamp.toLocalDateTime()
之类的方法这一事实中派生出来。

您更喜欢使用

java.time.Instant
的事实暗示在 PostgreSQL 中使用
TIMESTAMP WITH TIME ZONE
更好,默认情况下 JDBC(以及 jOOQ)映射到
OffsetDateTime
。您可以在 jOOQ 中将该类型重写为
INSTANT
,无需转换器: https://www.jooq.org/doc/latest/manual/code- Generation/codegen-advanced/codegen-config-database/codegen-database-forced-types/

您还可以在 PostgreSQL wiki 中看到此建议: https://wiki.postgresql.org/wiki/Don't_Do_This#Don.27t_use_timestamp_.28without_time_zone.29

您的具体配置

关于您映射类型的具体尝试:

.withIncludeExpression("timestamp")

这只适用于名为

timestamp
的列。您可能打算将强制类型应用于输入名称?

.withIncludeTypes("timestamp")

1
投票

很高兴 Lukas Eder 给出了几乎完整的解决方案提示 使用文档中的转换器 - 您始终可以实现自己的数据类型绑定

我们需要定义一个转换器

class JooqInstantConverter: Converter<LocalDateTime, Instant> {

  override fun to(databaseObject: Instant?): LocalDateTime? {
    if (databaseObject == null)
      return null
    return LocalDateTime.ofInstant(databaseObject, ZoneOffset.UTC)
  }

  override fun from(userObject: LocalDateTime?): Instant? {
    return userObject?.toInstant(ZoneOffset.UTC)
  }

  override fun toType(): Class<Instant> {
    return Instant::class.java
  }

  override fun fromType(): Class<LocalDateTime> {
    return LocalDateTime::class.java
  }
}

在代码生成中进行一些调整

ForcedType()
  .withUserType("java.time.Instant")
  .withConverter("xxx.JooqInstantConverter")
  .withTypes("TIMESTAMP")

人们可以深思熟虑地使用它,并牢记原始答案

© www.soinside.com 2019 - 2024. All rights reserved.