如何使用更新的 JPA 时间戳字段升级数据库?

How to upgrade database with newer JPA timestamp fields?

我有一个 Spring 引导应用程序 运行 使用 JPA 和 Hibernate 自动管理我的实体。当我创建这个应用程序时,我使用了不支持 Java 8 DateTime API 的旧版本 JPA。但是,在对 JPA 了解不多的情况下,我在我的实体中使用了 LocalDateTime 并且它起作用了!不必了解底层数据库结构真是太好了!

到现在为止...

我正在将 JPA 升级到支持 LocalDateTime 的版本,但我遇到了 JPA 使用此字段的错误。它曾经将此对象保存为我的 MySQL 数据库中的 VARBINARY (tinyblob) 字段,但现在它很聪明,希望它是 TIMESTAMP 类型。这意味着当我使用配置 spring.jpa.hibernate.ddl-auto=validate 启动我的应用程序时,我收到错误:

...
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: 
    Schema-validation: wrong column type encountered in column [answer_time] in table [user_answer]; 
    found [tinyblob (Types#VARBINARY)], but expecting [datetime (Types#TIMESTAMP)]

所以现在我有点不知道如何将这些字段转换为新的时间戳类型。我正在考虑使用 FlyWay 编写迁移脚本,但我不知道 JPA 如何将对象存储为 blob。当将 VARBINARY 字段打印为字符串时,它是这样的:

¬í sr java.time.Ser]º"H² xpw ã !;:;Ö@x

这是我的实体的样子(升级期间未更改):

@Entity
@Table(name = "user_answer")
public class UserAnswer {
    private Long id;
    private LocalDateTime answerTime;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public LocalDateTime getAnswerTime() {
        return answerTime;
    }

    public void setAnswerTime(LocalDateTime answerTime) {
        this.answerTime = answerTime;
    }
}

如何更新我的数据库,以便将用于存储 LocalDateTime 数据的旧 VARBINARY 字段转换为 TIMESTAMP 字段?

我会尝试什么(在备份数据库之后!):

  • 保留旧 JPA API + 实现(Hibernate)版本。
  • 保留旧的 LocalDateTime 字段。
  • 向您的实体添加另一个 java.sql.Date 字段。确保对其进行正确注释等,以便 Hibernate 确切知道应如何定义该列。
  • 对于所有实体:
    • 加载每个实体,读取LocalDateTime,转换并存储到DateTime字段,merge()
  • 删除 DateTime 字段。
  • 从 table 中删除旧 LocalDateTime 的列。
  • DateTime 字段的类型更改为 LocalDateTime
  • 升级 JPA API + 实现 (Hibernate) 版本。

  • JPA 实现(Hibernate?)应该将 DateTime 存储为 TIMESTAMP
  • JDBC 驱动程序应该能够将 TIMESTAMP 提取到 LocalDateTime

此外,考虑 ZonedDateTime 而不是 LocalDateTime