使用实体管理器刷新时在事务中的IDLE

时间:2012-09-12 09:53:31

标签: hibernate jpa transactions

我们正在使用hiberante,c3p0,postgresql作为持久层。 在运行数据密集型作业(主要是select / insert)时,其中一个开发人员决定在提交之前使用entityManager.flush(),就像这样

entityManager.getTransaction().begin()
insert n elements
entityManager.flush()
entityManager.getTransaction().commit()

一段时间后,运行数据密集型作业的所有线程似乎都被阻止了,我们发现他们正在等待池中的数据库连接。 池中所有连接处于“空闲处理”状态。 每次都可以复制这种情况。

删除flush()后,情况消失了。

有谁知道为什么会发生这种情况?

谢谢:D

1 个答案:

答案 0 :(得分:4)

hibernate有一个智能缓存系统,只需收集要执行的sql命令列表,然后在提交时执行它们。 Flush用于继续并部分执行这些命令。看起来这可能有所帮助,但是当你认为hibernate在没有刷新的情况下没有做任何事情之后,那么你就会导致数据库必须在短时间内处理大型事务而不是一次性处理。

这相当于将单张纸交给你的同事撕碎,而不是让他一次撕碎多张纸。将此与数据库可以锁定事务中间的记录这一事实相结合,从您第一次调用flush时开始,数据库专门执行命令的任务,直到您提交为止。如果数据库没有等待您并且同时拥有所有命令,那么它可以在完成实际工作所需的时间内完成。

简而言之,hibernate知道它在做什么。 Flush覆盖hibernate的正常运行,如果你不小心,可能会降低性能。如果订单很重要(例如在插入之前执行删除),您应该只使用flush。