Spring数据存储库@Query - 更新并返回修改后的实体

2022-09-03 15:46:44

让我们假设我们有一个带有自定义方法的Spring Data存储库接口...

@Modifying
@Transactional
@Query("UPDATE MyEntity SET deletedAt = CURRENT_TIMESTAMP WHERE id = ?1")
void markAsSoftDeleted(long id);

此方法只是设置实体的 deleteAt 字段,OK。有没有办法允许此方法返回 的更新版本?MyEntity

明显地。。。

@Modifying
@Transactional
@Query("UPDATE MyEntity SET deletedAt = CURRENT_TIMESTAMP WHERE id = ?1")
MyEntity markAsSoftDeleted(long id);

...不起作用,因为...

java.lang.IllegalArgumentException:修改查询只能使用 void 或 int/Integer 作为返回类型!

anyon是否知道另一种容易允许的方法,当然除了明显的“在存储库和调用者之间为此类事情添加服务层”......


答案 1

在批注上设置清除@Modifying自动属性。这将从 EntityManager 中清除所有未刷新的值。

@Modifying(clearAutomatically=true)
@Transactional
@Query("UPDATE MyEntity SET deletedAt = CURRENT_TIMESTAMP WHERE id = ?1")
MyEntity markAsSoftDeleted(long id);

要在提交更新之前刷新更改,最新的 spring-data-jpa 在 @ModifyingAttribute 上有另一个属性。但我认为它仍然在2.1.M1版本中。

@Modifying(clearAutomatically=true, flushAutomatically = true)

请检查相应的 jira 错误请求:https://jira.spring.io/browse/DATAJPA-806

另一种方法是实现自定义重新发布实现,并在完成查询执行后返回更新的实体。

参考:春季数据jpa自定义存储库实现


答案 2

有两种方法可以做到这一点:

JPA惯用的方法是首先加载实体,然后使用Java代码更改它们。

在事务中执行此操作将刷新对数据库所做的更改。

如果坚持执行批量更新,则需要将实体标记为更新的一部分。也许带有时间戳,也许更新本身已经标记了它们。然后,使用使用更新期间设置的标记的 select 语句重新加载它们。

请注意,您必须确保 实体在 中尚不存在,否则您将保留旧状态。这是其他答案推荐的目的。EntityManager@Modifying(clearAutomatically=true)


推荐