在 MySQL 数据库中,每个表都有一个列 updated
,其创建方式为
[...] `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
正如预期的那样,每行更新都会触发时间戳更新到 CURRENT_TIMESTAMP。当我通过 SQL shell、命令行、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]
此时,数据库条目已更新(“其他值”是当前值),但已更新
列仍为 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 一开始不触发更新,这正常吗?
有没有办法在同一事务中获取更新后的值?
最佳答案
您需要JPARepository.saveAndFlush() (或使用原始 JPA,EntityManager.refresh()
)在同一事务中从数据库获取更新的值。这会影响所有数据库生成的值。
JPA 不知道数据库内部的值正在发生变化,并且总是重新读取保存的值会对性能产生不利影响。这就是为什么在新事务中您会获得正确的值,因为数据实际上是从数据库中获取的。在同一笔交易中,该值仍在内存中,并假定未更改。
关于java - 使用Hibernate不会触发MySQL的 "ON UPDATE CURRENT_TIMESTAMP",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58746891/