我们正在开发一个(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 回答
重新附加分离实体时,摆脱
select
语句的一种可能方法是使用特定于Hibernate的update()
操作而不是merge()
.update()
无条件地运行update
SQL语句并使分离的对象持久化 . 如果会话中已存在具有相同标识符的持久对象,则会引发异常 . 因此,当您确定:它是一个很好的选择:分离对象包含应保存在数据库中的已修改状态
保存该状态是为该请求打开会话的主要目标(即,没有其他操作在该会话中加载具有相同ID的实体)
在JPA 2.0中,您可以按如下方式访问特定于Hibernate的操作:
See also:
一种可能的选择是使用StatelessSession作为更新语句 . 我've successfully used it in my '写重'的申请 .