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

标签 java hibernate jpa entitymanager

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

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

简而言之:我们正在寻找一种方法来在每次更新之前摆脱这些 SELECT 语句。有什么想法吗?

最佳答案

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

update() 无条件运行 update SQL 语句并使分离的对象持久化。如果 session 中已存在具有相同标识符的持久对象,则抛出异常。因此,当您确定:

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

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

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

另请参阅:

关于java - EntityManager 生命周期和持续的客户端-服务器-通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8038252/

相关文章:

java - 简单场景以 "integrity constraint violation"结尾

java - Spring Data JPA save() 返回实体

Spring Data JPA,在 CrudRepository 接口(interface)中参数化 @EntityGraph

java - Java 中的自定义注释

java - 为什么Spring Bean能够在Tomcat Servlet容器中运行而EJB却不能?

java - 将 Java 函数传递给 KFunction

java - JPQL(JPA)如果列表有交集则查找对象

java - Axon - 多个节点和多个数据库的重复段声明/未声明段

java - "java.sql.SQLException The column .. in table .. does not allow null values"尽管列值不为空

hibernate - 如何在Hibernate/JPA中为每个持久单元执行differnet import.sql?