JPA& Guice-persist:永久打开连接问题?

时间:2013-01-29 14:42:45

标签: java hibernate jpa entitymanager guice-persist

使用Hibernate,c3p0,Guice和Guice-persist,我们遇到了一个奇怪的问题,即事务后数据的连接没有释放到池中。

它似乎与JpaPersistService的完成方式有关,在一个threadLocal变量中缓存EntityManager:

private final ThreadLocal<EntityManager> entityManager = new ThreadLocal<EntityManager>();

我的问题是:

  • 我们应该删除guice-persist并将其替换为创建新entityManager的内容,然后在每次需要时关闭它(如建议here)?
  • 或者缓存entityManager是要走的路,我们应该用别的东西解决我们的问题吗?

(我们的问题:1)经典8h超时后mysqld杀​​死mysql连接,因此entityManager不再可用。可以通过启用c3p0 keep-alive来解决,但由于应用程序有时会长时间不使用,我们希望避免保持无用的主动连接。 2)似乎每个EntityManager都做一些缓存,并且entite在entityManager之间不一致。没看过如何解决这个问题)

2 个答案:

答案 0 :(得分:3)

终于找到了解决方案。

似乎这是guice-persist中的一个特殊错误。

如果EntityManager被注入UnitOfWork之外或者超出事务,那么就会创建一个永不关闭的EntityManager,导致出现奇怪的问题。

guice-persist的文档并未指出这一点。

如果您不在交易中或Provider<EntityManager>

,解决方案是始终注入EntityManager而不是直接注入UnitOfWork

答案 1 :(得分:2)

我相信你遇到了与我相同的问题:Guice JPA - "This connection has been closed." error

这一切都在Issue 730: Automatically started UnitOfWork is never ended

中得到了很好的描述
  

使用JpaPersistService时,如果您尝试访问   在一个活跃的UnitOfWork之外的EntityManager,Guice会   自动为您启动一个。但是,因为Guice没有(和   不知道何时结束这个UnitOfWork,它永远不会。

     

结果?违规线程将使用相同的EntityManager   在整个应用程序的生命周期。这是一个糟糕的状态   应用程序运行,我们不可避免地耗尽可用   一段时间后内存崩溃。

     

这里真正的杀手是,当你做完时,它并不是很明显   这个错误。唯一真正的提示是你得到的   不同线程之间数据库中的数据不一致(由于   EMs第一级缓存)或应用程序内存消耗   不断发展。   在我的情况下,池中的活动连接让我怀疑它,然后,当我打开详细日志记录时,我注意到应用程序根本没有从池中借用连接,而是重新使用已经由未公开的EntityManager。

实际上,报告的这个问题实际上有很多重复:http://code.google.com/p/google-guice/issues/list?can=1&q=UnitOfWork

因此,我认为注入EntityManager并不会带来太多好处。实际使用任何EntityManager方法时会发生此问题。您只需要确保每个访问都在UnitOfWork中。怎么做取决于你的申请。