在JPA / Hibernate中正确使用flush()

问题

我正在收集有关flush()方法的信息,但我不太清楚何时使用它以及如何正确使用它。根据我的阅读,我的理解是持久化上下文的内容将与数据库同步,即。即发布未完成的声明或刷新实体数据。

现在我得到了两个实体AB的以下场景(一对一的关系,但没有由JPA强制或建模).A有一个复合PK,它是手动设置的,还有一个自动生成的IDENTITY fieldrecordId。这个recordId应该写入entityB作为外键A。我在单笔交易中保存了A和5884898048。问题是自动生成的值A.recordId在事务中不可用,除非我在调用em.persist()onA之后显式调用了em.flush()。 (如果我有一个自动生成的IDENTITY PK,那么该值会在实体中直接更新,但这不是这里的情况。)
Canem.flush()在交易中使用它会造成任何伤害吗?


#1 热门回答(130 赞)

可能em.flush()的具体细节依赖于实现。总的来说,像Hibernate这样的JPA提供程序可以缓存它们应该发送到数据库的SQL指令,通常直到你实际提交事务为止。例如,你调用em.persist(),Hibernate记得它必须创建一个数据库INSERT,但在你提交事务之前实际上并没有执行指令。 Afaik,这主要是出于性能原因。

在某些情况下,你希望立即执行SQL指令;通常当你需要某些副作用的结果时,例如自动生成的键或数据库触发器。

Whatem.flush()用于清空内部SQL指令缓存,并立即将其执行到数据库。

底线:没有造成任何伤害,只有你可以有一个(次要的)性能命中,因为你重写JPA提供程序决定关于将SQL指令发送到数据库的最佳时机。


#2 热门回答(0 赞)

实际上,em.flush(),不只是发送缓存的SQL命令。它尝试将持久性上下文与基础数据库同步。如果缓存包含要同步的集合,则可能会导致流程耗费大量时间。

使用它的注意事项。