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 INSERT
、UPDATE
、DELETE
,直到提交或触发刷新。
【讨论】:
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 - 我应该更喜欢啥?
Amazon ELB 自动运行状况检查有啥作用,它有啥期望?