使用Hibernate PostgreSQL存储java.time.ZonedDateTime失败。

7

我有一个实体,它扩展了一个名为AbstractAuditingEntity的审计实体类,在其中一个字段中是

@CreatedDate
@Column(name = "created_date", nullable = false)
@JsonIgnore
private ZonedDateTime createdDate

上述字段与名为"created_date"且类型为"timestamp without time zone"的数据库字段有映射关系。
但是在保存此实体时,PostgresSQL会抛出以下错误:
Caused by: org.postgresql.util.PSQLException: ERROR: column "created_date" is of type timestamp without time zone but expression is of type bytea
  Hint: You will need to rewrite or cast the expression.

我在寻找同样的错误并在这里找到了解决方案:Postgresql UUID supported by Hibernate?

但是该解决方案适用于java.util.UUID,解决方案建议在具有UUID类型的字段上添加注释@Type(type="pg-uuid")

是否存在像pg-uuid这样的现成类型值,适用于ZonedDateTime?有关Hibernate @Type注释的不同值常量的任何参考链接吗?

还是应该编写自定义反序列化器类?如何编写此类反序列化器类,有任何参考链接吗?

PostgresSQL Version  : 9.6,
<liquibase-hibernate5.version>3.6</liquibase-hibernate5.version>

你能在日志记录器中启用org.hibernate.type的调试日志吗?如果类型已注册,您应该会发现类似于http://pastebin.com/t2xh5UvM的内容,并且应该可以正常工作。 - coladict
在Hibernate 5.2之前,Java 8时间类的处理是作为一个可选模块提供的。 - coladict
1个回答

8

对于Hibernate 5.2版本,它应该可以直接使用。

对于5.0版本,你可以添加一个支持库的依赖:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-java8</artifactId>
    <version>${hibernate.version}</version>
</dependency>

对于4.3版本,您可以使用JPA 2.1转换器:

@Converter
public class TimestampConverter implements AttributeConverter<ZonedDateTime, Timestamp> {
    @Override
    public Timestamp convertToDatabaseColumn(ZonedDateTime zonedTime) {
        if (zonedTime == null) {
            return null;
        }
        return new Timestamp(zonedTime.toInstant().toEpochMilli());
    }

    @Override
    public ZonedDateTime convertToEntityAttribute(Timestamp localTime) {
        if (localTime == null) {
            return null;
        }
        return ZonedDateTime.ofInstant(Instant.ofEpochMilli(localTime.getTime()), ZoneId.systemDefault());
    }
}

然后在你的属性上加上@Convert注解:

@Convert(converter = TimestampConverter.class)
private ZonedDateTime createdDate;

我注意到你的数据库列是TIMESTAMP。如果你的客户端时区有夏令时变化,它应该真正是TIMESTAMP WITH TIME ZONE


请注意,在您解决4.3问题时会丢失时区信息。 - jannis
1
Postgres不会在“TIMESTAMP”或“TIMESTAMP WITH TIME ZONE”中存储偏移信息。 - teppic

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