2016-11-29 56 views
1

我使用JPA的EclipseLink 2.0 Glassfish的3.1.2.2什么时候刷新并清除提交?

我想知道如果我叫

em.flush() 
em.clear() 

后的对象立刻将提交给数据库。我的问题是我做了很多交易,我得到了OutOfMemory。我想通过刷新事务的对象来避免这种情况。

后,我刷新和清晰的,我看不到将提交给数据库的任何直接的实体,我只能看到他们后,整个过程完成后,告诉我这是不实际commiting。

如果冲洗并明确不承诺:

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

2)为什么我不再使用OutOfMemory?

请告诉我,如果我是正确的:

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

回答

4

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

然而,变化成为“看得见”后,方可交易已经由容器(这里:Glassfish的)被正确执行,负责事务处理。有关参考,请参阅。的JPA Spec 2.0 7.6.1(第294)部分,其定义了:

新持久上下文开始当容器管理实体管理器被调用(具体而言,当EntityManager接口的方法之一是在一个JTA事务的范围调用),并且存在已经与JTA事务关联没有电流持久性上下文。持久化上下文被创建并且与JTA事务关联。

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

在第3.2节。在JPA Spec 2.0的4(同步到数据库),我们发现:

持久化实体的状态在交易同步到数据库提交

[..]

持久化提供者运行时被允许执行同步在其他时间数据库以及当事务是活动的。 flush方法可以被应用程序使用来同步force

它适用于与持久性上下文相关联的实体。可以使用EntityManager和Query setFlushMode方法来控制同步语义。第3.8.7节定义了FlushModeType.AUTO的效果。如果指定了FlushModeType.COMMIT,则在事务提交时会发生刷新;在其他时间,持久性提供者被允许(但不是必需)执行刷新。如果没有事务处于活动状态,则持久性提供程序不得刷新到数据库。

最有可能在您的情况下,容器(Glassfish)和/或您的应用程序配置为FlushModeType.COMMIT(* 1)。在FlushModeType.AUTO的情况下,它由持久性提供者(EclipseLink)决定,“负责确保持久性上下文中可能影响查询结果的所有实体的状态的所有更新对于处理查询“(第3.8.7节,第122页)

相比之下,clear()方法本身并没有提交任何东西。它只是将当前持久化上下文中的所有管理实体分开,从而导致未刷新(提交)的实体发生任何更改而丢失。有关参考资料,请参见p。 70链接JPA Spec

关于OutOfMemoryError,很难说在什么情况下导致了这种情况,因为您没有提供太多细节。不过,我想:

  1. 阅读JPA规范
  2. 检查你的环境是如何配置与前述部分
  3. 重新评估你的应用程序是如何采写/实施,对交易处理可能使错误的假设它在运行的容器。

相关的2,你可以检查你的persistence.xml是否配置

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

并将其更改为AUTO以查看是否有任何区别。

希望它有帮助。

脚注

* 1:但是,这是一个很好的猜测,因为你没有提供你的设置/环境的细节。

+2

伟大的信息。我想解释一下为什么我对此感到好奇:我正在使用JTA,但我也想控制事务提交的时间。我发现的是,如果我在托管bean上使用@TransactionManagement(TransactionManagementType.BEAN),然后使用UserTransaction,则可以“手动”控制此操作(即使使用JTA)。任何方式,这是我问,这是一个非常有趣和有用的答案。谢谢。 –

0

在JPA事务提交,JPA是自动冲水做。在第一次事务结束后,您应该在DB中看到对象,而不仅仅是在整个流程结束之后。检查是否真的做更多的交易或只有一个。

+0

我不是指多次交易,对不起。我的意思是在一次交易中使用多个INSERTS。 –