首页 文章

EntityManager生命周期和持久客户端 - 服务器通信

提问于
浏览
3

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

  • 首先,我们考虑了二级缓存 . 但是,我们发现无论何时添加或删除新项目,hibernate都会使它的Query-和Collection-Caches无效 .

  • 第二个想法,只要客户端登录服务器,我们就会评估是否保持EntityManager . 但是我想知道这是否是"best practice",因为存在一些缺点:线程安全,EntityManager实例的管理开销等 .

简而言之:我们正在寻找一种方法来在每次UPDATE之前删除那些SELECT语句 . 有什么想法吗?

2 回答

  • 2

    重新附加分离实体时,摆脱 select 语句的一种可能方法是使用特定于Hibernate的 update() 操作而不是 merge() .

    update() 无条件地运行 update SQL语句并使分离的对象持久化 . 如果会话中已存在具有相同标识符的持久对象,则会引发异常 . 因此,当您确定:它是一个很好的选择:

    • 分离对象包含应保存在数据库中的已修改状态

    • 保存该状态是为该请求打开会话的主要目标(即,没有其他操作在该会话中加载具有相同ID的实体)

    在JPA 2.0中,您可以按如下方式访问特定于Hibernate的操作:

    em.unwrap(Session.class).update(o);
    

    See also:

  • 0

    一种可能的选择是使用StatelessSession作为更新语句 . 我've successfully used it in my '写重'的申请 .

相关问题