使用 CrudRepository.save(Entity) 使用 spring-data-jdbc 插入具有预定义@ID 字段的实体

Using CrudRepository.save(Entity) to insert an Entity with predefined @ID field using spring-data-jdbc

我正在使用 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 here 将此操作视为 DbAction.Update.

所以,我想知道是否有任何方法可以使用 CrudRepository.save(Entity) 插入具有预定义 @ID 字段的新实体,因为我想使用 @DomainEvent挂钩 CrudRepository.save(Entity).

我觉得这是 spring-data-jdbc 中的一个错误。 只是想要一个 opinion/solution 这里。

根据 Spring Data Refrence Documetnation,底层 JPA EntiyManager 使用三种策略来确定一个实体是否是新的:

  1. Version-Property and Id-Property inspection (default): By default Spring Data JPA inspects first if there is a Version-property of non-primitive type. If there is the entity is considered new if the value is null. Without such a Version-property Spring Data JPA inspects the identifier property of the given entity. If the identifier property is null, then the entity is assumed to be new. Otherwise, it is assumed to be not new.

  2. Implementing Persistable: If an entity implements Persistable, Spring Data JPA delegates the new detection to the isNew(…) method of the entity. See the JavaDoc for details.

  3. Implementing EntityInformation: You can customize the EntityInformation abstraction used in the SimpleJpaRepository implementation by creating a subclass of JpaRepositoryFactory and overriding the getEntityInformation(…) method accordingly. You then have to register the custom implementation of JpaRepositoryFactory as a Spring bean. Note that this should be rarely necessary. See the JavaDoc for details.

对于您的情况,使用第二种策略可能是最有用的。希望对你有帮助。

编辑

有人向我指出,问题不是关于 JPA,而是 spring-data-jdbc。这是正确的,但不会更改答案,因为 Spring Data JDBC - Reference Documentation.

中记录了相同的行为