0

我想知道如何为每个用户线程设计实现一个 JPA EntityManager。由于 EM 是轻量级对象,因此为每个用户线程创建它们不应该是开销。我要解决的问题是单个 JSP 页面,其中包含对后端服务的多个(并行)JSON/AJAX 调用(通过控制器)。

我有一个实体管理器(具有扩展的持久性上下文),带有 Open EM In View Filter。它确实工作得很好,但只有当每页有一个用户线程(例如,一个 json 调用)时,或者换句话说,当我以串行方式访问 em 时。然而,当我从多个线程调用我的服务时,它并没有解决我的目的,因为 em 实例是共享的并且我得到了奇怪的错误(有时是对集合的共享访问,有时是关闭连接,我相信这是预期的)。

我在 Spring 3 和 hibernate 3.5 上使用 JPA。我将实体管理器(扩展)注入到我的服务中,如下所示:

@PersistenceContext(type = PersistenceContextType.EXTENDED)
protected EntityManager em;

我的只读服务方法被注释为

<tx:method name="get*" read-only="true" propagation="SUPPORTS"/>

所有其他方法,都注释为

<tx:method name="*" propagation="REQUIRED" rollback-for="Exception"/>

我想避免应用程序管理 em,因此没有去注入 EntityManagerFactory。另外,如果我选择将 EntityManager 注入 spring 控制器,当从两个线程并行调用同一个控制器时,我仍然会遇到问题!

有没有一种优雅的方式来实现对 em.xml 的线程安全访问?我还想避免锁定任何实体对象,这会使事情进一步复杂化。

由于来自同一页面的多个 ajax 调用是现代 Web 应用程序中非常常见的设计,我相信必须有一种简单且声明性的方式来实现这一点(无需回到使用拦截器等手动管理休眠会话)

4

3 回答 3

2

我不太明白你的问题。

每个线程的实体管理器是默认行为,但您使用EXTENDED. 您是否有任何具体原因将其配置为EXTENDED?如果没有,您只需将其删除:

@PersistenceContext
protected EntityManager em; 
于 2012-07-02T11:31:40.167 回答
0

这是使用 EM/Sessions 的最标准方式,并且有一些标准工具,如 OpenSessionInViewFilter(或 Interceptor),当 HTTP 请求进入您的 servlet 容器时创建一个会话。或者它可以是一个 Spring Transactional 支持,它在 AOP 的帮助下创建一个会话。这里的关键是使用已经存在的机制,或者,如果你有一些扩展,至少复制粘贴它们。Spring 在 TransactionSynchronizationManager 的帮助下通过将资源绑定/取消绑定到线程来实现这一点。您可以查看 Spring 源代码,或者这里是 session-per-conversation 模式的示例,它也使用相同的方法将资源绑定到线程。

于 2012-07-02T11:28:49.813 回答
0

Spring 有一个 Thread 范围,默认情况下是禁用的(请参阅第4.5 节 Bean 范围):

线程范围的 bean
从 Spring 3.0 开始,线程范围是可用的,但默认情况下没有注册。有关详细信息,请参阅SimpleThreadScope. 有关如何注册此或任何其他自定义范围的说明,请参阅第 4.5.5.2 节,“使用自定义范围”。

如果您激活范围,您可以将您的 entitymanagers 定义为scope=thread

于 2012-07-02T11:01:08.873 回答