在不更改实体数据的情况下更新 @Updatetimestamp

Posted

技术标签:

【中文标题】在不更改实体数据的情况下更新 @Updatetimestamp【英文标题】:Update @Updatetimestamp without changeing data of entity 【发布时间】:2021-05-14 09:33:33 【问题描述】:

ChildEntity 与 ParentEntity 具有多对一关系

ParentEntity,有一个:

@Version
@UpdateTimestamp
protected LocalDateTime modificationTime;

要求是,当 ChildRepository extends JPARepository 创建或修改 ChildEntity(在 @Transactional 上下文中)时,必须更新 ParentEntity Row 的 modifyTime

我们目前看到的唯一方法,就是创建一个方法updateModificationTime并显式设置它,想知道是否有更好的方法?

我们如何在不更改 ParentEntity 的任何数据的情况下更新 @UpdateTimestamp 注释的 modifyTime?

github 仓库: https://github.com/daveyx/spring-playground/tree/main/210427-datatest

测试用例: https://github.com/daveyx/spring-playground/blob/main/210427-datatest/src/test/java/com/example/datatest/child/ChildServiceIntegrationTest.java

【问题讨论】:

你试过用@DynamicUpdate注释实体了吗? 谢谢,尝试@DynamicUpdate 没有成功。此外,我们不喜欢这个注释的缺点 没有成功是什么意思?这也要求保存总是通过父集合,并且子集合级联MERGE 并使用@OptimisticLock。有什么缺点? 在通过父级保存而不更改数据时仅保存父级github.com/daveyx/spring-playground/blob/main/210427-datatest/… 时不成功。在没有@DynamicUpdate 的情况下,通过 Parent 保存也可以,但这不是我们想要的。我们要保存 Child 并触摸 Parent 以更新 @DynamicUpdate 的@UpdateTimestamp 缺点是 hibernate 需要立即创建 SQL 并且不能使用预定义的 SQL。 在这种情况下,您唯一的选择是使用例如entityManager.lock(parent, OPTIMISTIC_FORCE_INCREMENT) 【参考方案1】:

正如 Chris 所建议的,OPTIMISTIC_FORCE_INCREMENT 对我们来说似乎是一种“正确”的方式。 在事务上下文中获取父实体,更新 @UpdateTimestamp 注释属性:

public interface ParentRepository extends JpaRepository<ParentEntity, Long> 

@Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)
@Query("SELECT pe FROM ParentEntity pe WHERE pe.id = :parentId")
ParentEntity findByIdForceIncrement(@Param("parentId") Long parentEntityId);

【讨论】:

以上是关于在不更改实体数据的情况下更新 @Updatetimestamp的主要内容,如果未能解决你的问题,请参考以下文章

在不更新行版本的情况下检查实体的并发性

在不修改实体类(注释)或数据上下文(使用 fluentapi)的情况下禁用标识(自动递增)

如何在不更新具有多对多关系的子实体的情况下保留父实体?

在EF4中无法在不首先获取实体的情况下更新实体

如何在不更改实时数据库中的 downloadUrl 的情况下更新 android 中 Firebase 存储中的位图图像

VueJS 在不更改父数据的情况下编辑道具的正确方法