【问题标题】:EJB 3.1 Singleton + JPA + JSF design advice needed需要 EJB 3.1 Singleton + JPA + JSF 设计建议
【发布时间】:2011-10-27 03:24:06
【问题描述】:

给定:简单的 JSF webapp(没有 Seam),让 JSF bean 调用几个 EJB,这些 EJB 依次加载和持久化 JPA 实体。我想要的是对 ejb 使用 @Singleton 注释并注入 EntityManager 而不是 EntityManagerFactory:

@Singleton
public class MyEJB {
  @PersistenceContext(unitName = PERSISTENCE_UNIT_NAME)
  protected EntityManager em; // not EntityManagerFactory
}

Spec 说@Singleton 是线程安全的,支持并发和事务属性(来自我的观点)使得从 JSF bean 调用变得安全。我还期望性能优势,因为 EntityManager 不会为每个调用重新创建,并且它具有内部缓存能力。

我主要关心的是在我有多个单例的情况下对 JPA 实体的创建/更新操作,因此,长期存在的 EntityManager 数量相同。

  • 如果一个单例更新 JPA 实例会发生什么以及这些 更改填充到其他单例?
  • 由于我无法关闭实体管理器,是否需要刷新它 每个实体更新?
  • 如果这几个单例共享同一个实体会更好吗 经理?
  • 我只看到了几个这样的设计例子。为什么?有没有严重的 缺点?

非常感谢!

【问题讨论】:

    标签: jsf jpa jsf-2 ejb-3.0 ejb-3.1


    【解决方案1】:

    关于更改 Singleton EJB 的 LockType,我想提一件事。虽然总的来说这听起来是个好主意,但您应该记住,诸如 EntityManger 之类的资源不是线程安全的,因此应该提供适当的并发访问控制。您可以使用@Lock(WRITE) 注释访问非线程安全资源的方法,但是如果您的Singleton EJB 的几乎所有接口方法都访问此类资源,您将遇到与完全写锁定的情况几乎相同的情况。另一种方法是使用带有手动细粒度同步的 Bean 并发管理,但这也是一个值得商榷的决定。

    因此,一般而言,我更喜欢无状态 EJB 而不是单例,并在特定情况下使用后者。

    【讨论】:

      【解决方案2】:

      我还期望性能优势,因为 EntityManager 不会为每次调用重新创建,并且它具有内部缓存功能。

      您可能会使用单例来节省一些内存,但在您的应用程序中到处使用它可能会使其实际上变慢,因为只有一个 EJB 可以为您的应用程序的不同用户提供所有并发请求,容器会锁定对 EJB 的访问当它忙于服务一个请求时,它不能服务另一个请求。但是,使用锁类型(即@Lock(WRITE)@Lock(READ))可以在一定程度上缓解这种情况。

      当您希望使用 EJB 计时器定期执行一段代码或定期更新缓存等时,单例非常有用。

      如果一个单例更新 JPA 实例会发生什么,以及这些更改如何填充到其他单例?

      不应与非单例 EJB 的行为方式有任何不同。

      由于我无法关闭实体管理器,是否需要在每次实体更新时刷新它?

      如果您使用 CMT,则不会。在每笔交易结束时,一切都会自动刷新。

      如果这几个单例共享同一个实体管理器会更好吗?

      对我来说似乎是过早的优化。只需让容器为您注入 EM。

      我只看到了几个这样的设计例子。为什么?有什么严重的缺点吗?

      已经解释过了。

      【讨论】:

      • 这个答案很好,但是如果您提到注入的 EM 实际上是每个事务 EM 的代理,它可能会消除混乱。见stackoverflow.com/questions/7010470/…
      • Behrang,特别感谢@Lock。只读操作的性能显着提高,在我的情况下快 5 倍。
      猜你喜欢
      • 2011-11-13
      • 2011-05-30
      • 2013-11-26
      • 2011-03-01
      • 2014-10-22
      • 1970-01-01
      相关资源
      最近更新 更多