Java 8 休眠中的 LocalDate 错误地映射到 TIMESTAMP

Java 8 LocalDate in hibernate wrongly mapped to TIMESTAMP

我使用 Spring boot 1.4.2,它带来了 hibernate 5.0.11 (JPA 2.1)。 我想在我的实体中使用 Java 8 次 类,因此包括 hibernate-java8.

我的实体定义了一个 LocalDate 字段。

@Entity
@Table(name = "my_alarms_timeline", indexes = {...})
public class MyAlarm {
    ...
    @Column(name = "validity_date")
    @NotNull
    private LocalDate validityDate;
}

我希望将其映射到我的 H2 数据库中的日期。

在我的数据库中,我将其声明为 validity_date DATE NOT NULL,

当我尝试 运行 测试时,出现以下错误:

[INFO] Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: 
    Schema-validation: wrong column type encountered in column [validity_date] in table [my_alarms_timeline]; 
    found [date (Types#DATE)], but expecting [timestamp (Types#TIMESTAMP)]

令我惊讶的是,如果我将数据库定义更改为 validity_date TIMESTAMP NOT NULL,,我会得到错误

Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: 
    Schema-validation: wrong column type encountered in column [validity_date] in table [my_alarms_timeline]; 
    found [timestamp (Types#TIMESTAMP)], but expecting [date (Types#DATE)]

这只是上一条消息的反向消息。

我也尝试使用 AttributeConverter<LocalDate, java.sql.Date> 而不是包含 hibernate-java8,但这会产生相同的错误结果。

我必须做什么,才能将我的 LocalDate 正确映射到数据库中的日期?

我还尝试将 LocalDateTime 字段映射到 TIMESTAMP,这没有问题...

我没有在 Spring 中使用它,但在 "standard" JPA 中,我做了类似的事情:

@Converter(autoApply = true)
public class OffsetDateTimeAttributeConverter implements AttributeConverter<OffsetDateTime, Timestamp> {
    @Override
    public Timestamp convertToDatabaseColumn(OffsetDateTime entityValue) {
        if( entityValue == null )
            return null;

        return Timestamp.from(Instant.from(entityValue));
    }

    @Override
    public OffsetDateTime convertToEntityAttribute(Timestamp databaseValue) {
        if( databaseValue == null )
            return null;

        return OffsetDateTime.parse(databaseValue.toInstant().toString());
    }
}

我的 table 有 "timestamp with timezone" 列。然后我的@Entity 使用 OffsetDateTime。你应该能够用这样的东西在你的数据类型之间进行转换。

所以我通过在 @Column 注释中添加 columnDefinition="DATE" 得到它 运行。

@Entity
@Table(name = "my_alarms_timeline", indexes = {...})
public class MyAlarm {
    ...
    @Column(name = "validity_date", columnDefinition = "DATE")
    @NotNull
    private LocalDate validityDate;
}

不确定为什么没有其他人看到这个问题...

我怀疑您的项目中某处有以下代码:

@EntityScan(basePackageClasses = { Application.class, Jsr310JpaConverters.class })

如果您正在使用 Hibernate 5.x,您应该删除对 Jsr310JpaConverters.class 的引用,否则 Hibernate 和 Spring 都将尝试处理 Java 8 日期和时间对象。这可能会导致一些非常不稳定的行为(例如,当 运行 在不使用 UTC 的机器上时,LocalDate 实例以错误的值持久化)。

您还应该删除任何出现的:

@Column(columnDefinition = "DATE")

如果您需要它,则表明您的休眠配置存在严重错误。