flush 和 clear 什么时候提交?

When does flush and clear commit?

我正在使用 JPA EclipseLink 2.0 和 Glassfish 3.1.2.2

我想知道我打电话后是否

em.flush() 
em.clear()

对象立即提交到数据库。我的问题是我进行了如此多的交易,以至于我得到 ​​OutOfMemory。我想通过刷新交易的对象来避免这种情况。

在我刷新并清除之后,我看不到任何立即提交到数据库的实体,我只能在整个过程完成后才能看到它们,这告诉我这实际上并没有提交。

如果 flush 和 clear 没有提交:

1) 它实际上是做什么的?

2) 为什么我不再出现 OutOfMemory?

请告诉我是否正确:

在我的 RAM 中分配的对象已发送到数据库,但更改尚未提交。这仅意味着我清除了 RAM,对象现在位于数据库服务器中,但事务尚未提交。

在提交 JPA 事务时,JPA 会自动进行刷新。您应该在第一个事务结束后立即在数据库中看到对象,而不仅仅是在整个流程结束后。检查是否真的进行了更多交易或仅进行了一次交易。

实体在 transaction commit 时间同步到连接的数据库。如果您只有 n = 1 个正在进行的事务(此处:JTA/container 管理),一个或多个实体的更改会在您调用 flush() 时写入数据库在 EntityManager 实例上。

但是,只有在负责事务处理的容器(此处为 Glassfish)正确执行事务后,更改才会变为 "visible"。供参考,请参阅。 JPA Spec 2.0 的第 7.6.1 节(第 294 页)定义:

A new persistence context begins when the container-managed entity manager is invoked (Specifically, when one of the methods of the EntityManager interface is invoked) in the scope of an active JTA transaction, and there is no current persistence context already associated with the JTA transaction. The persistence context is created and then associated with the JTA transaction.

The persistence context ends when the associated JTA transaction commits or rolls back, and all entities that were managed by the EntityManager become detached.

JPA Spec 2.0 的第 3.2.4 节(与数据库同步)中,我们发现:

The state of persistent entities is synchronized to the database at transaction commit.

[..]

The persistence provider runtime is permitted to perform synchronization to the database at other times as well when a transaction is active. The flush method can be used by the application to force synchronization.

It applies to entities associated with the persistence context. The EntityManager and Query setFlushMode methods can be used to control synchronization semantics. The effect of FlushModeType.AUTO is defined in section 3.8.7. If FlushModeType.COMMIT is specified, flushing will occur at transaction commit; the persistence provider is permitted, but not required, to perform to flush at other times. If there is no transaction active, the persistence provider must not flush to the database.

很可能在您的场景中,容器 (Glassfish) and/or 您的应用程序配置为 FlushModeType.COMMIT(*1)。如果 FlushModeType.AUTO 到位,则由持久性提供者 (EclipseLink) 负责,“ 负责确保对持久性上下文中所有实体的状态进行所有更新,这可能会影响查询结果对查询处理可见。”(第 3.8.7 节,第 122 页)

相比之下,clear() 方法本身不提交任何内容。它只是将所有托管实体从当前持久性上下文中分离出来,从而导致对尚未刷新(提交)的实体的任何更改丢失。有关参考,请参见第 15 页。 70 个链接 JPA Spec.

关于OutOfMemoryError,很难说是在什么情况下造成的,因为你也没有提供太多细节。但是,我会:

  1. 阅读 JPA 规范的上述部分
  2. 检查您的环境是如何配置的
  3. 重新评估您的应用程序 written/implemented,可能会对 运行 所在容器的事务处理做出错误假设。

关于2.,你可以检查一下你的persistence.xml是否配置了

<property name="eclipselink.persistence-context.flush-mode" value="COMMIT" />

然后改成AUTO看看有没有区别

希望对您有所帮助。

脚注

*1:但这是一个很好的猜测,因为您没有提供关于 setup/environment 的那么多细节。