Spring JpaRepository:delete(),在同一事务中使用后续的save()

时间:2014-12-31 08:29:30

标签: java database spring transactions spring-data-jpa

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

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

我实际上设法通过添加

来绕过它
repository.flush();

但我真的不知道为什么我需要这个冲洗()。

1 个答案:

答案 0 :(得分:8)

因为repository.flush()通过调用EntityManager.flush()来刷新对数据库的更改。因此,当您在delete()之后刷新更改时,会执行sql并且以下保存没有问题。

如果不调用flush,则由持久性提供程序决定何时刷新更改,事务提交时间为截止日期。提供者也不会以任何特定顺序刷新更改,因此有时您的操作会成功,有时则不会。通常,提供者会等到提交时间刷新,但您可以通过设置刷新模式来影响它:

for entitymanager
EntityManager.setFlushMode(FlushModeType type);

or for query
Query.setFlushMode(FlushModeType type);

我确信Spring数据JPA中还有一个等效的设置,但我不知道它是哪一个。

但请注意,立即刷新更改会降低性能,因此在使用时应小心。在您的特定情况下,最好更新实体,然后删除它,然后使用相同的业务键保留新实体。