java - 使用 CrudRepository.save(Entity) 使用 spring-data-jdbc 插入具有预定义 @ID 字段的实体
问题描述
我CrudRepository.save(Entity)
用来插入一个@ID
已经填充的实体。
我收到以下异常。
Caused by: org.springframework.dao.IncorrectUpdateSemanticsDataAccessException: Failed to update entity [com.comanyname.repository.Entiy.class]. Id [ed384316-9c22-4b63-90fd-ec02fdac2b86] not found in database.
我可以理解这个问题,因为 @ID
字段已经填充,这里的 AggregateChangeExecutor 将此操作视为 DbAction.Update。
所以,我想知道是否有任何方法可以CrudRepository.save(Entity)
用来插入具有预定义@ID
字段的新实体,因为我想@DomainEvent
在 CrudRepository.save(Entity) 上使用钩子。
我有点觉得这是spring-data-jdbc
. 只是想在这里发表意见/解决方案。
解决方案
根据 Spring Data Refrence Documetnation,底层 JPA EntiyManager 使用三种策略来确定实体是否是新的:
Version-Property 和 Id-Property 检查(默认):默认情况下,Spring Data JPA 首先检查是否存在非原始类型的 Version-property。如果值是 ,则该实体被认为是新的
null
。如果没有这样的版本属性,Spring Data JPA 会检查给定实体的标识符属性。如果标识符属性是null
,则假定实体是新的。否则,假定它不是新的。实施
Persistable
:如果实体实施Persistable
,Spring Data JPA 将新的检测委托给isNew(…)
实体的方法。有关详细信息,请参阅JavaDoc。实现
EntityInformation
:您可以通过创建子类并相应地覆盖方法来自定义实现中EntityInformation
使用的抽象。然后,您必须将自定义实现注册为 Spring bean。请注意,这应该很少需要。有关详细信息,请参阅JavaDoc。SimpleJpaRepository
JpaRepositoryFactory
getEntityInformation(…)
JpaRepositoryFactory
在您的情况下,使用第二种策略可能是最有用的。希望能帮助到你。
编辑
有人向我指出,问题不是关于 JPA,而是关于 spring-data-jdbc。这是正确的,但不会改变答案,因为Spring Data JDBC-Reference Documentation中记录了相同的行为。