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

huangapple go评论58阅读模式
英文:

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 在这里 将此操作视为 DbAction.Update。

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

我有点觉得这是 spring-data-jdbc 中的一个 bug。
只是想要一个意见/解决方案。

英文:

I'm using CrudRepository.save(Entity) to insert an Entity with @ID already populated.

I'm getting the following exception.

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.

I can understand the issue as @ID field is already populated,
AggregateChangeExecutor here is treating this action as DbAction.Update.

So, I wanted to know if there is any way I can use CrudRepository.save(Entity) to insert a new entity with a predefined @ID field as I've wanted to use @DomainEvent hook on CrudRepository.save(Entity).

I kind of feel that this a bug in spring-data-jdbc.
Just wanted an opinion/solution here.

答案1

得分: 11

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

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

  2. 实现Persistable:如果一个实体实现了Persistable接口,Spring Data JPA会将新的检测委托给实体的isNew(…)方法。有关详细信息,请参阅JavaDoc

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

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

编辑

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

英文:

According to the Spring Data Refrence Documetnation, the underlying JPA EntiyManager uses three strategies to determine if an entity is new:

> 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.

In your case, using the second strategy might be the most useful. Hope it helps.

Edit

It was pointed out to me, that the question was not about JPA, but spring-data-jdbc. This is correct but does not change the answer since the same behaviour is documented in Spring Data JDBC - Reference Documentation.

huangapple
  • 本文由 发表于 2020年7月29日 20:44:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/63153924.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定