JPA中flush的确切目的是什么

问题描述 投票:0回答:3

一些令人困惑的解释: 冲洗();刷新是将底层持久存储与内存中保存的持久状态同步的过程。它将更新或插入到正在运行的事务中的表中,但它可能不会提交这些更改。

如果无论如何更改仅在提交后才会保留在数据库中,那么为什么要在代码中间刷新。

运行刷新后,如果对托管对象进行任何更改,则会抛出异常,或者这些更改将被同步,然后将被保留。如果它们同步了,那么为什么首先要刷新呢?

java jpa entitymanager
3个回答
18
投票

理论上,您(作为 JPA 的用户)永远不应该(或在绝对罕见的情况下)拨打

flush()

Flushing是同步底层持久化的过程 将持久状态存储在内存中

换句话说,在

flush()
上,所有插入、更新、删除或实际在数据库上调用的任何语句,在
flush()
之前,数据库上什么也没有发生。刷新是由事务提交或某些类型的数据库读取引起的。例如,如果您执行 JPQL 查询,则必须执行
flush()
才能从数据库获取正确的结果。但很高兴知道这一点,并且完全由 JPA 实现来处理。

在某些情况下,您可能想自己控制此刷新,然后您可以使用

flush()
来调用它。

编辑回答评论中的问题:

并非每次读取都需要刷新,请考虑这种情况(一个事务):

  1. 读懂一个人
    Person p = em.find(Person.class, 234)
  2. 更新人物
    p.setAge(31)
  3. 阅读建筑物
    Building b = em.find(Building.class, 123
  4. 使用 JPQL 查询读取建筑物
    select b from Building b where b.id = 123

自动 flush 仅在 4. 之前发生,因为 Eclipselink 无法确定您将要读取的内容,因此在发生此读取之前,数据库中该人的年龄必须是最新的。 3.之前不需要刷新,因为Eclipselink知道对一个人的更新不会影响建筑物。

要使用乐观锁定,您必须实现它。请在此处阅读有关

@Version
注释的信息:https://blogs.oracle.com/carolmcdonald/entry/jpa_2_0_concurrency_and。如果没有它,您的实体将不会使用乐观锁定并且“最后更新获胜”。


3
投票

当事务提交时,实体管理器会为您执行刷新操作。在某些情况下,比如在容器管理的事务中处理乐观锁,您可能需要手动调用flush方法来捕获并处理特定的锁定异常。


0
投票

如果您手动保存两个实体,则需要生成的 id。

entityManagerInstance.persist(entity1);
entityManagerInstance.flush();
entity2.setForeignKeyToEntity1(entity1.getId());
entity2.create();
© www.soinside.com 2019 - 2024. All rights reserved.