【问题标题】:JPA & Guice-persist: permanently opened connection issue?JPA & Guice-persist:永久打开的连接问题?
【发布时间】:2013-01-13 04:14:43
【问题描述】:

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

好像和JpaPersistService的做法有关,把EntityManager缓存在一个threadLocal变量中:

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

我的问题是:

  • 我们是否应该删除 guice-persist 并将其替换为创建一个新的 entityManager 然后在每次需要时关闭它(如建议的here)?
  • 或者缓存 entityManager 是可行的方法,我们应该用其他方法解决问题?

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

【问题讨论】:

    标签: java hibernate jpa entitymanager guice-persist


    【解决方案1】:

    终于找到了解决办法。

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

    如果 EntityManager 被注入到 UnitOfWork 之外或事务之外,则会创建一个永不关闭的 EntityManager,从而导致奇怪的问题。

    guice-persist 的文档没有指出这一点。

    如果您不在事务或UnitOfWork 中,则解决方案是始终注入Provider&lt;EntityManager&gt; 而不是直接注入EntityManager

    【讨论】:

    【解决方案2】:

    相信你也遇到了和我一样的问题:Guice JPA - "This connection has been closed." error

    这一切都在Issue 730: Automatically started UnitOfWork is never ended中得到了很好的描述

    使用 JpaPersistService 时,如果您尝试访问 EntityManager 在活动的 UnitOfWork 之外,Guice 将 自动为您启动一个。然而,正如 Guice 没有(和 不能)知道什么时候结束这个 UnitOfWork,它永远不会。

    结果?有问题的线程将被同一个 EntityManager 卡住 在应用程序的整个生命周期中。这是一个糟糕的状态 应用程序运行,我们不可避免地耗尽了可用的 一段时间后记忆并崩溃。

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

    其实这个问题其实有不少重复报告:http://code.google.com/p/google-guice/issues/list?can=1&q=UnitOfWork

    所以我认为注入 EntityManager 并没有多大用处。当您实际使用任何 EntityManager 方法时,就会出现问题。您只需要确保每个访问都在 UnitOfWork 内。具体如何操作取决于您的应用程序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-15
      • 1970-01-01
      相关资源
      最近更新 更多