【问题标题】:Produce an Entitymanager with extended persistence context via CDI通过 CDI 生成具有扩展持久性上下文的 Entitymanager
【发布时间】:2012-10-17 06:50:45
【问题描述】:

我们正在尝试构建一个系统,该系统根据登录用户(多租户类型)“生成”一个实体管理器。因此我们实现了一个这样的无状态 ejb:

@Stateless
@TransactionAttribute(TransactionAttributeType.SUPPORTS)
public class CustomEntityManagerFactory {

  @PersistenceContext(unitName = "EM1")
  private EntityManager em1;

  @PersistenceContext(unitName = "EM2")
  private EntityManager em2;

  @Produces
  @RequestScoped
  public EntityManager getEntityManager() {
    // check which entitymanager to return
  }
}

entitymanager 是这样注入的:

@Stateless
public class EmployeeService {

  @Inject
  private EntityManager em;

  ...

}

只要只需要一个没有扩展持久性上下文的实体管理器(在无状态 ejb 中),这个生产者就可以工作。不幸的是,我们也有一些有状态的 ejb,它们需要扩展的持久性上下文。有没有办法为此目的实现 CDI 生产者,还是这种方法仅适用于带有事务实体管理器的无状态 ejb?

【问题讨论】:

  • 我不明白这个问题。详细说明问题所在。例如,发布的代码是否有效?你能粘贴一些不起作用的代码吗?
  • 是的,只要将 entitymanager 注入到无状态 ejb 中,我的代码就可以工作。但是,如果我需要有状态 ejb 中的实体管理器(使用 @PersistenceContext(type = PersistenceContextType.EXTENDED) 注释),我该怎么办?我也尝试为此构建生产者方法,但我认为 CDI 生命周期与 EJB 不同生命周期,所以我要么总是得到一个新的实体管理器(@RequestScoped),要么总是得到相同的实体管理器(@SessionScoped - 这会导致异常,因为 em 已经绑定)。不幸的是,在这种情况下,您的建议对我没有帮助.

标签: ejb cdi entitymanager multi-tenant stateful


【解决方案1】:

我猜你需要这个: 在这里创建两个工厂:

@ApplicationScoped
public class EntityManagerFactoryProducer {

    private static EntityManagerFactory factory;
    private static EntityManagerFactory factory2;

    @Produces
    public EntityManagerFactory getEntityManagerFactory(InjectionPoint ip) {
    // if the field is named exactly factory2 then factory2 is produced
    if (ip.getMember().getName().equals("factory2")) {

        if (factory2 == null) {
        factory2 = Persistence.createEntityManagerFactory("EM2");
        }
        return factory2;
    }

    else {
        if (factory == null) {
        factory = Persistence.createEntityManagerFactory("EM1");
        }
        return factory;
    }
    }

使用工厂创建EntityManagers

public class EntityManagerProducer {
    @Inject
    private EntityManagerFactory factory;

    @Inject
    private EntityManagerFactory factory2;

    @Produces
    @RequestScoped
    public EntityManager getEntityManager() {
        return factory.createEntityManager();
    }

    @Produces
    @RequestScoped
    @MyCustomQualifier
    public EntityManager getEntityManager2() {
        return factory2.createEntityManager();
    }

}

用于实体管理器之间不同的限定符

@Qualifier
@Retention(RUNTIME)
@Target({FIELD })
public @interface MyCustomQualifier {
    @Nonbinding
    public String value() default "";
}

最终用途:

@Inject
EntityManager em;

@Inject
@MyCustomQualifier
EntityManager em2;

当然,您可以使用限定符来区分工厂,而不是检查字段的名称。我只是想更深入地了解答案。

【讨论】:

  • 工厂小心!您将从它们那里获得一个应用程序管理实体管理器,这与容器管理的不同之处在于您必须处理诸如关闭它们之类的管理任务。
猜你喜欢
  • 2016-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-19
  • 2020-11-28
  • 2017-03-19
  • 1970-01-01
相关资源
最近更新 更多