需要EJB 3.1单例+ JPA + JSF设计建议



给定:简单的JSF web应用程序(没有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是线程安全的,支持并发性和事务属性,这(从我的pov)使得它可以安全地从JSF bean调用。我还期望性能方面的好处,因为EntityManager不会为每个调用重新创建,而且它的内部缓存能力。

我在这里主要关注的是在JPA实体上创建/更新操作,当我有几个单例时,结果是相同的长寿entitymanager计数。

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

提前感谢!

我也期望性能的好处,因为EntityManager不被重新创建每个调用和它的内部缓存能力。

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

当您想要使用EJB计时器周期性地执行一段代码,或者周期性地更新缓存等时,单例非常有用。

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

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

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

如果使用CMT,则不需要。在每个事务结束时,所有内容都将自动刷新。

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

在我看来是不成熟的优化。就让集装箱给你注射EM吧。

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

已经解释。

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

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

相关内容

  • 没有找到相关文章

最新更新