Использование Hibernate не вызывает MySQL «ON UPDATE CURRENT_TIMESTAMP» - PullRequest
3 голосов
/ 07 ноября 2019

В БД MySQL каждая таблица имеет столбец updated, который создается как

[...] `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

Как и ожидалось, каждое обновление строки вызывает обновление метки времени для CURRENT_TIMESTAMP. Это верно, когда я обновляю строку через оболочку SQL, командная строка, DBeaver, Workbench НО

Работа с Hibernate (Spring Boot 2, Spring Data JPA) не работает. Я имею в виду псевдокод, такой как:

[Tx]
entity = repository.findById(1) --> Returns my entity with updated == 1L 
entity.setProperty("other value")
repository.save(entity)
[/Tx]

На этом этапе запись в БД была обновлена ​​(«другое значение» является текущим значением), но столбец updated по-прежнему равен 1L, где должно быть CURRENT_TIMESTAMP

Я использовал для обхода этой проблемы либо

  • , аннотируя свойство как @UpdateTimestamp, либо h
  • , аннотируя метод с помощью @PrePersist && @PreUpdate, который бы программно устанавливалтекущая временная метка перед оператором UPDATE SQL

Проблема с обоими подходами заключается в том, что у меня нет обновленного значения до тех пор, пока я не выйду из Tx:

[Tx]
entity.getUpdated() == 1L
entity.setName("other")
repository.save(entity) // at this point the updated is still == 1L
repository.findById()  // at this point the updated is still == 1L
[/Tx]

[Tx]
repository.findById()  // good timestamp value
[Tx]

нормально, что MySQL вообще не запускает обновление?

Есть ли способ получить обновленное значение в той же транзакции?

1 Ответ

3 голосов
/ 07 ноября 2019

Вам необходимо JPARepository.saveAndFlush () (или с необработанным JPA, EntityManager.refresh()), чтобы получить обновленное значение из базы данных в той же транзакции. Это влияет на все значения, сгенерированные базой данных.

JPA не знает, что значения изменяются внутри базы данных, и для производительности было бы плохо всегда перечитывать сохраненное значение. Вот почему в новой транзакции вы получаете правильные значения, так как данные фактически извлекаются из базы данных. В той же транзакции значение все еще находится в памяти и предполагается, что оно не изменилось.

...