在条件下在无状态会话 Bean 中注入特定的 EntityManager

Posted

技术标签:

【中文标题】在条件下在无状态会话 Bean 中注入特定的 EntityManager【英文标题】:inject specific EntityManager in stateless SessionBean on condition 【发布时间】:2012-10-22 06:04:56 【问题描述】:

我目前正在处理调用无状态会话 Bean 以与数据库交互的 Web 应用程序。我的问题是关于这样的应用程序如何调用同一个会话 bean,以便后者可以选择必须使用哪个实体管理器来访问数据库。

目前我管理这种情况,启动不同的 Jboss 实例,监听不同的端口,并且在每个实例中我部署了相同的会话 Bean 池,并且一个或多个 Web 应用程序必须处理相同的数据库。换句话说,每个 Jboss 实例都包含一定数量的 Web 应用程序、一个持久性单元(persistence.xml in META-INF jar containing the @Entity's) 和会话 bean 池都在一个耳朵内。 主要弱点在哪里是不言而喻的:我需要处理更多不同的数据库,我必须维护尽可能多的 Jboss 实例,这主要是不可持续的,但不仅是因为资源原因。

我的最后一个问题是:部署不同的 Web 应用程序调用会话 bean 的最佳做法是什么?

提前致谢

Stfn

【问题讨论】:

【参考方案1】:

使用 CDI @Producer 方法执行此操作。我假设您知道如何区分您拥有的众多 @PersistenceContexts,因此您制作了一个制作人,如下所示:

// first inject all the entity managers that you have into your CDI producer
@PersistenceContext(name = "name0")
private EntitManager em0;

@PersistenceContext(name = "name1")
private EntitManager em1;

@PersistenceContext(name = "name2")
private EntitManager em2;

...

// then have your producer method with logic to chose the right EntityManager to be returned
@Produces @MyPersistenceContext
public EntityManager obtainTheRightEM(InjectionPoint caller) 
    if (hasCondition0(caller)) 
        return em0;
     else if (hasCondition1(caller)) 
        return em1;
     else if (hasCondition2(caller)) 
        return em2;
     else 
        ...
    

然后在您的@EJBs 中将@PersistenceContext 替换为@Inject @MyPersistenceContext

此外,根据您的特定问题,可能需要也可能不需要创建@MyPersistenceContext 限定符。如果您有特定的配置值,您需要向下传递给生产者,以便决定从生产者返回哪个EntityManager,请考虑在您的自定义限定符中使用一些@Nonbinding 字段.

您最终可能会因为只有一个 @EJB 部署而侥幸。

干杯!希望这会有所帮助。

【讨论】:

【参考方案2】:

你想要达到的目标并不是很清楚......

是否使用不同的数据库来分离来自不同客户的数据(每个数据库具有相同的结构)?为此,Hibernate 提供了一些多租户支持 (http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html/ch16.html),但 JPA 中尚未标准化。

您可以通过任何方式将不同的耳朵放在同一个 Jboss 实例上(您将需要使用不同的 Web 上下文名称)以减少资源消耗。 (但是您将失去操作系统级别的进程控制,一个租户可以使用所有资源而无法确保另一个租户获得最少的资源。)

【讨论】:

非常感谢 Kazaag 的回答。让我再解释一下。 非常感谢您的回答。让我再解释一下。数据库不同但具有相同的关系。我已经尝试过您概述的第二个解决方案,但不起作用。在同一个容器中(这是我的第一次尝试)我有会话 Bean 冲突(使用了第一个调用的会话 bean对于后续请求,无论应用程序是否调用 id,在会话 bean 池级别缺乏隔离),唯一的方法是重命名会话 bean 接口,这是我为了维护更轻量的代码而避免的。所以,让我试验第一个概述的解决方案。 Stfn 如果 EJB 位于不同的耳朵,它们应该有不同的全局名称,因此通过 JNDI 检索它们应该会给您相应的名称。

以上是关于在条件下在无状态会话 Bean 中注入特定的 EntityManager的主要内容,如果未能解决你的问题,请参考以下文章

如何在无状态会话 bean 中创建多线程?

从无状态 Bean 中获取 JDBC 连接对象

如何将超时设置为 EJB 方法(在无状态 bean 中)

无状态会话 Bean 与单例会话 Bean

无法在无状态 EJB 中注入 JMS 队列

使用 JPA / Hibernate 在无状态应用程序中进行乐观锁定