Как обновить базу данных новыми полями меток времени JPA? - PullRequest
1 голос
/ 08 июня 2019

У меня есть приложение Spring Boot, работающее с использованием JPA и Hibernate для автоматического управления объектами. Когда я создавал это приложение, я использовал более старую версию JPA, которая не поддерживала Java 8 DateTime API. Однако, не имея большого знания о JPA, я использовал LocalDateTime в своих сущностях, и это сработало! Не было необходимости знать о базовой структуре базы данных!

До сих пор ...

Я обновляю JPA до версии, которая поддерживает LocalDateTime, и я сталкиваюсь с ошибкой при использовании JPA этого поля. Раньше он сохранял этот объект как поле VARBINARY (tinyblob) в моей базе данных MySQL, но теперь он умен и ожидает, что он будет иметь тип 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;
    }
}

Как мне обновить базу данных, чтобы она преобразовывала старые VARBINARY поля, которые использовались для хранения LocalDateTime данных, в TIMESTAMP поля?

1 Ответ

1 голос
/ 09 июня 2019

Что бы я попробовал (после резервного копирования БД!):

  • Сохранить старые версии реализации JPA API + (Hibernate).
  • Сохранить старое поле LocalDateTime.
  • Добавьте еще одно поле java.sql.Date к вашей сущности.Убедитесь, что он правильно аннотирован и т. Д., Чтобы Hibernate точно знал, как должен быть определен столбец.
  • Для всех объектов:
    • Загрузите каждый объект, прочитайте LocalDateTime, преобразуйте и сохраните егов поле DateTime, merge().
  • Удалите поле DateTime.
  • Удалите столбец для старого LocalDateTime из таблицы.
  • Измените тип поля DateTime на LocalDateTime.
  • Обновите версии реализации JPA API + (Hibernate).

  • JPA impl (Hibernate?) Должен хранить DateTime как TIMESTAMP.
  • Драйвер JDBC должен иметь возможность выбрать TIMESTAMP в LocalDateTime.

Такжерассмотрим ZonedDateTime вместо LocalDateTime.

...