何时刷新并清除提交?

AFP*_*555 3 jpa transactions jta eclipselink jpa-2.0

我正在将JPA EclipseLink 2.0与Glassfish 3.1.2.2一起使用

我想知道我打电话后是否

em.flush() 
em.clear()
Run Code Online (Sandbox Code Playgroud)

这些对象立即提交到数据库。我的问题是我要进行很多交易OutOfMemory。我想通过刷新事务对象来避免这种情况。

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

如果刷新和清除没有提交:

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

2)为什么我不再获得OutOfMemory?

请告诉我我是否正确:

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

MWi*_*ner 5

实体在事务 提交时同步到连接的数据库。如果你只有N = 1个正在进行中的事务(此处:JTA /容器管理),对一个或多个实体的变化被写入到数据库调用的那一刻flush()EntityManager实例。

但是,只有在负责事务处理的容器(在这里:Glassfish)正确执行了事务之后,更改才变为“可见”。供参考,请参阅。JPA Spec 2.0的 7.6.1节(第294页)中定义:

当活动的JTA事务的范围内调用容器管理的实体管理器(具体来说,当EntityManager接口的方法之一被调用)时,新的持久性上下文开始,并且当前没有持久性上下文与JTA相关联交易。创建持久性上下文,然后将其与JTA事务关联。

当关联的JTA事务提交或回滚时,持久上下文结束,并且由EntityManager管理的所有实体都被分离。

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

持久实体的状态在事务提交时同步到数据库。

[..]

当事务处于活动状态时,还允许持久性提供程序运行时在其他时间与数据库执行同步。该flush方法可由应用程序用来强制同步。

它适用于与持久性上下文关联的实体。的EntityManager和查询setFlushMode方法可用于控制同步语义。的效果FlushModeType.AUTO在3.8.7节中定义。如果FlushModeType.COMMIT指定,刷新将在事务提交时进行;允许(但不是必需)持久性提供程序在其他时间执行刷新。如果没有活动的事务,则持久性提供程序不得刷新到数据库。

在您的方案中,很可能容器(Glassfish)和/或您的应用程序配置为FlushModeType.COMMIT(* 1)。在FlushModeType.AUTO适当的情况下,由持久性提供程序(EclipseLink)决定,该负责“确保对持久性上下文中所有实体状态的所有更新都可能对查询的结果可见,而这些更新可能会影响查询的结果”查询。 ”(第3.8.7节,第122页)

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

关于OutOfMemoryError,由于您也未提供太多详细信息,因此很难说出在什么情况下是什么原因造成的。但是,我会:

  1. 阅读JPA规范的上述部分
  2. 检查环境的配置方式,以及
  3. 重新评估应用程序的编写/实现方式,从而可能对运行它的容器的事务处理做出错误的假设。

与2.相关,您可以检查其persistence.xml是否配置

<property name="eclipselink.persistence-context.flush-mode" value="COMMIT" />
Run Code Online (Sandbox Code Playgroud)

并进行更改AUTO以查看是否有任何区别。

希望能帮助到你。

脚注

* 1:但这是一个很好的猜测,因为您没有在设置/环境中提供太多详细信息。

  • 很棒的信息。我想解释一下为什么对此感到好奇:我在使用JTA,但我也想控制何时提交事务。我发现,如果我在托管bean的顶部使用@TransactionManagement(TransactionManagementType.BEAN),然后使用UserTransaction,则可以“手动”控制此功能(即使使用JTA)。无论如何,这是我问的,这是一个非常有趣且有用的答案。谢谢。 (2认同)