我使用JPA EclipseLink 2.0和Glassfish 3.1.2.2
我想知道我打电话后是否
em.flush()
em.clear()
对象立即提交到数据库。我的问题是我做了很多交易,我得到OutOfMemory
。我希望通过刷新事务的对象来避免这种情况。
在刷新并清除之后,我无法看到任何立即实体提交到数据库,我只能在整个过程完成后看到它们,这告诉我这实际上并没有提交。
如果刷新和清除不提交:
1)它实际上做了什么?
2)为什么我不再使用OutOfMemory?
请告诉我,我是否正确:
我的RAM中分配的对象被发送到数据库,但尚未提交更改。这只意味着我清除了我的RAM,对象现在在数据库服务器中,但事务尚未提交。
答案 0 :(得分:4)
实体在交易 提交时间与已连接的数据库同步。如果您只有 n = 1 正在进行的事务(此处:管理JTA /容器),那么当您在{{1}上调用flush()
时,一个或多个实体的更改将写入数据库实例。
但是,只有在负责事务处理的容器(此处为:Glassfish)正确执行事务之后,更改才会变为“可见”。供参考,请参阅。 JPA Spec 2.0的第7.6.1节(第294页)定义:
在容器管理的实体管理器(具体地,当调用EntityManager接口的方法之一)中调用容器管理的实体管理器时,新的持久化上下文开始一个活动的JTA事务,并且当前没有与JTA事务关联的持久性上下文。创建持久性上下文,然后与JTA事务关联。
当关联的JTA事务提交或回滚时,持久性上下文结束,并且由EntityManager管理的所有实体都将分离。
我们发现JPA Spec 2.0的第3.2.4节(与数据库同步):
持久实体的状态在事务提交时与数据库同步。
[..]
当事务处于活动状态时,允许持久性提供程序运行时在其他时间执行与数据库的同步。应用程序可以使用
EntityManager
方法强制同步。它适用于与持久性上下文关联的实体。
flush
和Query setFlushMode方法可用于控制同步语义。EntityManager
的效果在3.8.7节中定义。如果指定FlushModeType.AUTO
,则在事务提交时将发生刷新;允许持久性提供程序,但不是必需的,以便在其他时间执行刷新。如果没有活动的事务,则持久性提供程序不得刷新到数据库。
最有可能在您的方案中,容器(Glassfish)和/或您的应用程序配置为FlushModeType.COMMIT
(* 1)。在FlushModeType.COMMIT
到位的情况下,由持久性提供程序(EclipseLink)决定“负责确保对持久性上下文中所有实体的状态的所有更新可能会影响结果该查询对查询的处理是可见的。“(第3.8.7节,第122页)
相比之下,FlushModeType.AUTO
方法本身并不提交任何内容。它只是将所有托管实体从当前持久化上下文中分离出来,从而导致未被刷新(提交)的实体的任何更改丢失。供参考,请参见p。链接JPA Spec中的70个。
关于clear()
,很难说出在什么情况下造成这种情况的原因,因为你没有提供太多细节。但是,我会:
与2.相关,您可以检查OutOfMemoryError
是否配置
persistence.xml
并将其更改为<property name="eclipselink.persistence-context.flush-mode" value="COMMIT" />
以查看是否存在任何差异。
希望它有所帮助。
脚注
* 1:但这是一个很好的猜测,因为你没有在你的设置/环境中提供那么多细节。
答案 1 :(得分:0)
在JPA事务提交中,JPA自动执行刷新。您应该在第一个事务结束后立即在DB中看到对象,而不仅仅是在整个进程结束之后。检查是否真的做了更多的交易或只做一次。