Postgres中没有时区默认CURRENT_TIMESTAMP的字段TIMESTAMP的JPA模型类?

Posted

技术标签:

【中文标题】Postgres中没有时区默认CURRENT_TIMESTAMP的字段TIMESTAMP的JPA模型类?【英文标题】:JPA Model Class for field TIMESTAMP WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP in Postgres? 【发布时间】:2019-11-18 03:43:31 【问题描述】:

我在 Postgres 中使用了 Java 8 和 Postgres-11 和 Spring Boot 2.1.6.RELEASE。我已经使用了this question 和this question,但我真的很想使用 Java 8 Date API 而不是 Java 7。

CREATE TABLE note(
    note_id serial PRIMARY KEY,
    message varchar(255) NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

我已经创建了如下模型类,但与我需要的不匹配。

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Entity
public class Note extends AuditEnabledEntity
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "note_id")
    private int noteId;
    
    @Column(name = "message")
    private String message;
    
    @Column(name = "created_at")
    private LocalDateTime createdAt;

【问题讨论】:

【参考方案1】:

类型错误

LocalDateTime 在这里是错误的类型。正如其 Javadoc 中所解释的那样,该类不能代表片刻。

该类故意没有时区或从 UTC 偏移的概念。所以它代表一个日期和一天中的时间,例如“2019 年 1 月 23 日中午”,但不知道是东京、巴黎还是蒙特利尔的中午,例如,三个非常不同的时刻相隔几个小时。所以这种类型适用于标准 SQL 类型TIMESTAMP WITHOUT TIME ZONE - without,而不是 with

更多讨论请见:What's the difference between Instant and LocalDateTime?

正确的类型

对于标准 SQL 类型 TIMESTAMP WITH TIME ZONE,您应该使用 Java 类型 InstantOffsetDateTimeZonedDateTime。在这三个中,JDBC 4.2 只需要对第二个 OffsetDateTime 的支持。

检索。

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

从 Postgres 检索的值将始终采用 UTC。 SQL 标准没有指定这种行为,因此数据库会有所不同。在 Postgres 中,任何发送到 TIMESTAMP WITH TIME ZONE 类型字段的值都会调整为 UTC。检索到的值采用 UTC。

存储。

myPreparedStatement.setObject( … , odt ) ;

从 UTC(零偏移)调整为特定地区(时区)人们使用的挂钟时间。

ZoneId z = ZoneId.of( "Asia/Tokyo" ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

JPA

我不使用 JPA,我更喜欢保持简单。

但是根据this Answer,JPA 2.2 支持 java.time 类型。

Hibernate 也支持 java.time

【讨论】:

以上是关于Postgres中没有时区默认CURRENT_TIMESTAMP的字段TIMESTAMP的JPA模型类?的主要内容,如果未能解决你的问题,请参考以下文章

使用 node-postgres 在 utc 中获取 Postgres“没有时区的时间戳”

将 Postgres 中没有时区的 DateTime 字段从中欧时间转换为 UTC

Rails 和 Postgres:迁移到 change_colomn 时出现错误“无法强制转换为没有时区的时间戳”

Postgres 通过时区转换防止时间戳

如何在 Postgres 9.3 中获取当前时区名称?

使用 Spring Data 的 postgres 中的时间戳出错:列 $COLUMN_NAME 是没有时区的时间戳类型,但表达式是 bytea 类型