Spring JpaRepository:delete()和后续保存()在同一事务中

iyfjxgzm  于 2023-08-02  发布在  Spring
关注(0)|答案(2)|浏览(177)

我的实体有自动生成的主键(id)和业务键(命名空间)。我需要通过替换旧的来更新记录。因此,我通过业务密钥搜索它,删除它并保存一个新实体。如果每个操作都在它自己的事务中,则此方法有效。但是一旦我把它们都放在同一个事务中,在执行保存()的时候,delete()还没有执行,所以我得到了一个约束冲突。

transactionTemplate.execute(status -> {
    MyEntity oldEntity = repository.findByNamespace(namespace);
    if (oldEntity != null) {
        repository.delete(oldEntity);
    }
    repository.save(newEntity);
    return null;
});

字符串
实际上我成功地绕过了它

repository.flush();


但是我真的不明白为什么我需要这个同花。

li9yvcax

li9yvcax1#

因为repository.flush()通过调用EntityManager.flush()来刷新数据库中的更改。因此,当您在delete()之后刷新更改时,SQL将被执行,并且随后的保存将不会有任何问题。
如果不调用flush,则由持久性提供程序来决定何时刷新更改,事务提交时间是截止日期。此外,提供程序不会以任何特定的顺序刷新更改,因此有时您的操作成功,有时却失败。通常,提供程序会等到提交时刷新,但您可以通过设置刷新模式来影响该操作:

for entitymanager
EntityManager.setFlushMode(FlushModeType type);

or for query
Query.setFlushMode(FlushModeType type);

字符串
我确信SpringdataJPA中也有一个等效的设置,但我不知道是哪一个。
但是请注意,立即刷新更改会降低性能,因此在使用它时应小心。在您的特定情况下,最好更新实体,然后删除它,然后使用相同的业务密钥持久化新实体。

cfh9epnr

cfh9epnr2#

我遇到了同样的问题,我需要首先删除对象,然后创建一个新对象,但得到了违反约束的异常,因为删除没有被刷新到DB,插入也因此失败。
我尝试了delete*方法的各种不同的方法,但只有deleteInBtraiatch(Iterable<T> entity)起作用。

相关问题