基于容器的EntityManager的动态@PersistenceContext unitName属性

时间:2012-01-09 05:32:17

标签: java-ee jpa ejb-3.0 eclipselink glassfish-3

基本上,我想要做的是将 @PersistenceContext 的' unitName '属性赋值给我在运行时从Session获得的值。

详细说明;

我的应用程序将是一个SaaS应用程序,我将为每个不同的租户提供单独的数据库。我正在使用 Glassfishv3 并管理实体基于容器的,因此我没有明确地从 EntityManagerFactory 获取任何实例。我在创建实体经理时所做的就是;

@PersistenceContext(unitName = "DBNAME")
private EntityManager entityManager;

我需要根据当前用户传递unitName属性。它不应该是硬编码的。

我已更新 Eclipselink 2.3但所有示例都是从EMF创建一个实例,您可以传递属性Map

Map memberProps = new HashMap();
memberProps.put("memberPu1", props1);
memberProps.put("memberPu2", props2);

Map props = new HashMap();
props.put("eclipselink.jdbc.exclusive-connection.mode", "Always");
props.put("eclipselink.composite-unit.properties", memberProps);

EntityManager em = emf.createEntityManager(props);

不太可能在我的应用程序中,容器执行该作业,因此我无法执行此操作

EntityManager em = emf.createEntityManager(props);

即使我使用JNDI定义拥有 persistence.xml 中的所有持久性单元和类,我也无法告诉应用服务器它应该使用哪个DB(持久性单元)时间

任何帮助将不胜感激

2 个答案:

答案 0 :(得分:9)

注释中的值无法在运行时分配,因此您需要找到可以创建多个PersistenceContext的策略。如果你可以使用CDI,它可能会让你的生活更轻松。

使用CDI,您可以按如下方式创建生产者:

public class EntityManagerProducer {

  @PersistenceContext(unitName="firstUnit") private EntityManager firstEntityManager;
  @PersistenceContext(unitName="secondUnit") private EntityManager secondEntityManager;

  @Produces
  public EntityManager getEntityManager(InjectionPoint injectionPoint) {
     if(<your_first_criteria>) {
       return firstEntityManager;
     } else if (<your_second_criteria>) {
       return secondEntityManager;
     }
  }

然后你可以使用你的制作人方法,例如你的DAO:

@Inject private EntityManager entityManager;

编辑:我可能会建议您使用@Qualifier注释,因为它可以清楚地显示EntityManager的来源。

答案 1 :(得分:1)

您需要使用应用程序管理的持久性单元,而不是容器。

即。 Persistence.createEntityManagerFactory()

您仍然可以使用JTA,而不是注射。