【问题标题】:JPA Web application management strategiesJPA Web 应用程序管理策略
【发布时间】:2010-12-11 21:12:01
【问题描述】:

我们目前正在开发一个使用 JPA 作为数据访问层的 J2EE Web 应用程序。我们目前正在考虑几种不同的策略来在我们的应用程序中使用缓存。

  1. 为每个请求创建一个 EntityManager
    • 在请求范围内获取缓存,但在请求结束时丢失缓存
    • 可以轻松回滚整个请求的任何更改
  2. 为每个 Http 会话创建一个 EntityManager
    • 在会话范围内获取缓存
    • 使事务变得更复杂,必须为每个请求创建一个新事务,然后能够回滚每个请求的更改

我在 Hibernate 文档中看到了这两种策略。我的问题是哪个更广泛使用,如果我们对每个会话执行 EntityManager,我们是否会在不同的请求线程中使用相同的 EntityManager 时遇到同步问题?

【问题讨论】:

    标签: java hibernate jpa jakarta-ee


    【解决方案1】:

    更广泛使用的方法是为每个请求创建一个EntityManager。但是,这应该对您隐藏。你应该使用一些依赖注入机制(spring/CDI/EJB)来注入正确的EntityManager@PersistenceContext

    如果您对在 bean 是某种单例(一个无状态 bean/一个范围单例的 spring bean)的常见情况下如何实现这一点感兴趣 - 容器实际上在目标对象中注入了一个代理。并且每次查询代理时,它都会获得 当前 EntityManager 实例,该实例(至少在 spring 的情况下)绑定到 ThreadLocal(在这种情况下为请求)

    更新:如果你想在自制框架中实现这个功能,那么使用 cglib / javassist / JDK 代理并将其注入到 @PersistenceContext 所在的位置。一个请求 = 线程。在每个需要数据访问的请求上,创建一个新的EntityManager 并将其存储在ThreadLocal 中。记得最后清理它,因为 servlet 容器重用线程。您可以从代理获取当前的ThreadLocal 值。

    但如果您对项目的了解不远,那么我建议您转向更稳定的东西,例如 spring、cdi 或 guice。

    【讨论】:

    • 我们有一个围绕 Stripes mvc 框架构建的本地 ioc 容器,我们目前使用它来将 EntityManager 注入我们需要的地方。但这回答了我的问题,我们倾向于每个请求,但只是想与世界其他地方核实。
    【解决方案2】:

    您使用的是什么服务器?它应该能够为您注入一个 EntityManger,而不是要求应用程序处理它。

    【讨论】:

    • Glassfish v2(IT 要求)。出于好奇,如果实体管理器被注入,应用服务器会在每次注入时创建一个新的实体管理器吗?还是可以配置为每个请求或会话重用一个?
    • 我在 Glassfish v2 上使用了注入。任何 J2EE5 服务器都应该这样做。我不确定它是如何专门创建类的。我假设它使用一个池,就像数据库连接一样。
    猜你喜欢
    • 2015-03-18
    • 2015-07-30
    • 2012-01-05
    • 2011-08-30
    • 2014-07-28
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 2016-02-23
    相关资源
    最近更新 更多