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

use*_*148 8 java postgresql spring 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.
Run Code Online (Sandbox Code Playgroud)

我可以理解这个问题,因为 @ID字段已经填充,这里的AggregateChangeExecutor将此操作视为 DbAction.Update。

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

我感觉这是一个错误spring-data-jdbc。只是想在这里提出意见/解决方案。

Ber*_*ard 12

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

\n
\n
    \n
  1. Version-Property 和 Id-Property 检查(默认):默认情况下,Spring Data JPA 首先检查是否存在非原始类型的 Version-property。如果存在,且值为 ,则该实体被视为新实体null。如果没有这样的版本属性,Spring Data JPA 将检查给定实体的标识符属性。如果标识符属性为null,则假定该实体是新的。否则,就认为它不是新的。

    \n
  2. \n
  3. 实现Persistable:如果实体实现了Persistable,Spring Data JPA 会将新的检测委托给isNew(\xe2\x80\xa6)实体的方法。有关详细信息,请参阅JavaDoc 。

    \n
  4. \n
  5. 实现EntityInformation:您可以通过创建子类并相应地重写方法来自定义实现EntityInformation中使用的抽象。然后,您必须将 的自定义实现注册为 Spring bean。请注意,这应该很少有必要。有关详细信息,请参阅JavaDoc 。SimpleJpaRepositoryJpaRepositoryFactorygetEntityInformation(\xe2\x80\xa6)JpaRepositoryFactory

    \n
  6. \n
\n
\n

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

\n

编辑

\n

有人向我指出,问题不是关于 JPA,而是关于 spring-data-jdbc。这是正确的,但不会改变答案,因为Spring Data JDBC - 参考文档中记录了相同的行为中记录了相同的行为。

\n