EntityManager.flush 有啥作用,为啥需要使用它?

Posted

技术标签:

【中文标题】EntityManager.flush 有啥作用,为啥需要使用它?【英文标题】:What does EntityManager.flush do and why do I need to use it?EntityManager.flush 有什么作用,为什么需要使用它? 【发布时间】:2013-07-16 05:08:19 【问题描述】:

我有一个 EJB,我在其中将一个对象保存到数据库中。在我看到的一个示例中,一旦保存了这些数据(EntityManager.persist),就会调用 EntityManager.flush();为什么我需要这样做?我正在保存的对象未附加,也未在该方法的后面使用。事实上,一旦保存方法返回,我希望资源会被释放。 (示例代码也在 remove 调用中执行此操作。)

if (somecondition) 
    entityManager.persist(unAttachedEntity);
 else 
    attachedEntityObject.setId(unAttachedEntity.getId());

entityManager.flush();

【问题讨论】:

【参考方案1】:

EntityManager.flush() 将实际的 SQL 命令发送到 DB。

持久性框架通常在后台管理事务。 因此无法保证刷新的查询会成功提交

EntityManager.flush() 总是在事务提交之前被持久性框架在后台自动调用。

EntityManager.persist() 只将实体注册到持久化上下文,而不向数据库发送任何 SQL 语句。这意味着您不会在persist() 之后获得自动生成的 ID。您只需传递持久对象,最终在flush() 之后获得 ID。您可以自己致电flush()提前获取这些 ID。但是这又不是事务的结束,所以它可以回滚甚至更多:其他事务/线程/进程/服务器可能会看到更改(通过幻读),然后然后消失取决于数据库引擎和当前和外部事务的隔离级别!

【讨论】:

感谢您的解释!不过还有一个补充:我刚刚对此进行了测试,EntityManager.persist() 和 EntityManager.flush() 都可以在没有 EntityManager.persist() 的情况下为您提供自动生成的 ID。使用 mysql5InnoDBDialect 在 @Transactional 注释方法中测试(以防万一)【参考方案2】:

EntityManager.flush() 操作可用于在事务提交之前将所有更改写入数据库。默认情况下,在提交事务之前,JPA 通常不会将更改写入数据库。这通常是可取的,因为它在需要之前避免了数据库访问、资源和锁定。它还允许对数据库写入进行排序和批处理以实现最佳数据库访问,并保持完整性约束并避免死锁。这意味着当您调用持久化、合并或删除数据库时,不会执行 DML INSERTUPDATEDELETE,直到提交或触发刷新。

【讨论】:

EntityManager.flush() 操作可用于在事务提交之前将所有更改写入数据库。 -> 这并不完全正确。您仍然需要提交,flush 仅将 SQL 语句发送到数据库而不提交。在没有提交的情况下触发刷新仍然不会实际插入任何实体。如果您尚未刷新,commit 将为您刷新,但刷新不会提交.. EntityManager.flush() 会将数据发送到数据库,但此时对其他人不可见。相反,更改的数据库条目将获得行锁。但只有在 commit() 之后,更改才会对其他人可见,并且锁会被移除。 @user2081279 实际上,确切的语义取决于有效的事务隔离设置:每个数据库的默认值不同,并且大多数数据库提供各种可能的设置。【参考方案3】:

所以当您调用EntityManager.persist() 时,它只会使实体由EntityManager 管理,并将其(实体实例)添加到Persistence Context。显式flush() 将使现在驻留在Persistence Context 中的实体移动到数据库(使用SQL)。

如果没有flush(),这(将实体从Persistence Context 移动到数据库)将在提交与此Persistence Context 关联的事务时发生。

【讨论】:

【参考方案4】:

EntityManager.persist() 使实体持久化,而 EntityManager.flush() 实际上在您的数据库上运行查询。

因此,当您调用EntityManager.flush() 时,会在数据库中执行插入/更新/删除关联实体的查询。此时将知道任何约束失败(列宽、数据类型、外键)。

具体的行为取决于flush-mode是AUTO还是COMMIT。

【讨论】:

【参考方案5】:

调用EntityManager.flush(); 将强制数据立即保存在数据库中,而EntityManager.persist() 不会(取决于EntityManager 的配置方式:FlushModeType (AUTO 或 COMMIT) 默认设置为 AUTO 和如果设置为 COMMIT,则刷新将自动完成,当事务提交时,数据到底层数据库的持久性将被延迟)。

【讨论】:

FlushModeType 的描述不正确:基本上 AUTO 意味着如果您更改一个实体,然后进行可能返回该实体的 SELECT 查询,AUTO 将强制刷新对该实体的更改在 SELECT 执行之前。

以上是关于EntityManager.flush 有啥作用,为啥需要使用它?的主要内容,如果未能解决你的问题,请参考以下文章

Entitymanager.flush() VS EntityManager.getTransaction().commit - 我应该更喜欢啥?

sigmoid是啥有啥作用,或者有啥功能!

Amazon ELB 自动运行状况检查有啥作用,它有啥期望?

SynchronizationContext 有啥作用?

BluetoothGatt.setCharacteristicNotification() 有啥作用?

“@”有啥作用?