我们正在开发(JavaSE-)应用程序,该应用程序通过持久的tcp连接与许多客户端进行通信。客户端连接,执行一些/许多操作(已更新为SQL数据库)并关闭应用程序/与服务器断开连接。我们正在使用Hibernate-JPA,并使用ThreadLocal-variable自行管理EntityManager-lifecycle。实际上,到目前为止,我们在每个客户端请求上都创建了一个新的EntityManager-instance。最近,我们进行了一些分析,发现休眠在每个UPDATE语句之前对数据库执行SELECT查询。这是因为我们的实体处于分离状态,并且每个新的EntityManager都会首先将该实体附加到持久性上下文。当服务器处于负载状态时,这会导致大量的SQL开销(因为我们有一个写繁重的应用程序),并且我们试图消除这种泄漏。

  • 首先,我们考虑了二级缓存。但是,我们发现,每当添加或删除新项目时,休眠都会使它的查询缓存和集合缓存失效。
  • 再三考虑,只要客户端在服务器上登录,我们就评估是否保持EntityManager正常运行。但是我不知道这是否是“最佳实践”,因为存在一些缺点:线程安全,EntityManager实例的管理开销等。

  • 简而言之:我们正在寻找一种在每次UPDATE之前摆脱那些SELECT语句的方法。有什么想法吗?

    最佳答案

    重新连接分离的实体时摆脱select语句的一种可能方法是使用特定于Hibernate的update()操作而不是merge()
    update()无条件运行update SQL语句,并使分离的对象持久化。如果会话中已经存在具有相同标识符的持久对象,则它将引发异常。因此,当您确定以下情况时,这是一个不错的选择:

  • 分离的对象包含应保存在数据库中的已修改状态
  • 保存该状态是为该请求打开会话的主要目标(即,没有其他操作在该会话中加载具有相同ID的实体)

  • 在JPA 2.0中,您可以按以下方式访问特定于Hibernate的操作:
    em.unwrap(Session.class).update(o);
    

    另请参阅:
  • 11.6. Modifying detached objects
  • 07-24 09:36
    查看更多