java Spring JpaRepository:delete() 与随后的 save() 在同一事务中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27718343/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 12:16:23  来源:igfitidea点击:

Spring JpaRepository: delete() with subsequent save() in the same transaction

javadatabasespringtransactionsspring-data-jpa

提问by Pavel Petrov

My entity has both autogenerated primary key (id) and business key (namespace). I need to update the record by replacing the old one. So, I'm searching it by business key, delete it and save a new entity. This works if each operation in it's own transaction. But once I put all of them in the same transaction, by the time save() is executed, delete() wasn't executed yet, so I get a constraint violation.

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

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

I actually managed to bypass it by adding

我实际上设法通过添加绕过它

repository.flush();

But I don't really get why do I need this flush().

但我真的不明白为什么我需要这个flush()。

采纳答案by miljanm

Because repository.flush() flushes the changes to the database by calling EntityManager.flush(). So when you flush the changes after delete(), sql gets executed and the following save will have no problems.

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

If you don't call flush it is up to persistence provider to determine when to flush the changes with transaction commit time being the deadline. Also providers don't flush changes in any particular order, so it may happen that sometimes your operation succeeds and sometimes it doesn't. Usually, providers wait until the commit time flush, but you can influence that by setting a flush mode:

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

for entitymanager
EntityManager.setFlushMode(FlushModeType type);

or for query
Query.setFlushMode(FlushModeType type);

There is an equivalent setting in Spring data JPA also, I'm sure, but I don't exactly know which one it is.

Spring data JPA 中也有一个等效的设置,我敢肯定,但我不完全知道它是哪一个。

Note however, that immediately flushing the changes reduces the performance, so you should be careful when using it. In your particular case it is better to update the entity then it is to delete it and then persist the new one with the same business key.

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