【问题标题】:Is it possible to pass EntityManager as a parameter through multiple beans?是否可以通过多个 bean 将 EntityManager 作为参数传递?
【发布时间】:2019-03-28 19:47:36
【问题描述】:

我知道我可以做到以下几点:

public class MyDao{

  private EntityManager em;

  public void setEm(EntityManager em){
     this.em = em;
  }
  ...

然后,使用@PostConstuct 传递EntityManager

public class MyBean{
  private EntityManager em;

  @Inject
  private MyDao myDao;

  @PostConstruct
  private void init(){
    myDao.setEm(em);
  }
...

但是由于我的应用程序的架构限制,我不能直接将 MyDao 注入 MyBean,我应该通过 MyBusinessDao 类,所以我尝试了以下方法,但我在 MyDao 中获得了 EntityManager 值上的 nullPointerExeception

    public class MyBean{

    private EntityManager em;

    public MyBean(){
        em = createEntityManager();
    }

    private EntityManager createEntityManager(){
        //dynamically create the EntityManager
    }

    @Inject
    private MyBusinessDao myBusinessDao;

    @PostConstruct
    private void init(){
       myBusinessDao.setEm(em);
    }
   ...

我在 MyBusinessDao 中注入 MyDao:

 public class MyBusinessDao {

    private EntityManager em;

    @Inject
    private MyDao myDao;

    @PostConstruct
    private void init(){
      myDao.setEm(em);
    }
    ...

我应该提到我没有使用J2EE 容器

【问题讨论】:

  • 只需在你真正需要的地方声明 em,并用@PersistenceContext 注释它。为什么要在不需要的地方注入它,然后尝试将其传递给其他 bean?
  • @JBNizet 感谢您的回答,事实上,所有(业务、doa 和实体)类都将打包在一个 jar 中并由另一个团队使用,该团队将提供自己的 entityManager,这就是为什么它应该是上级声明
  • 不,不应该。豆子就是豆子。
  • 您能否建议我另一种将EntityManager 从我的 Bean 传递到 Dao 的方法
  • 正如我所说,不要。将其注入您需要的地方。 DAO 是一个 bean,它存在于 EntityManager 可用的应用程序中,因此 EM 将被注入 DAO。

标签: jpa ejb cdi


【解决方案1】:

您可以实现一个 CDI 生产者方法,通过 CDI 注入提供 EntityManager。

@ApplicationScoped
class EntityManagerProducer {

   @PersistenceContext(...)
   private EntityManager em;

   @Produces
   @RequestScoped
   public EntityManager produceEm() {
      return em;
   }
}

你也可以注入EntityManagerFactory,在producer方法中调用emf.createEntityManager(),实现CDI-Disposer方法,在作用域结束前关闭EntityManager。

public void dispose(@Disposes EntityManager em) { ... }

如果您有多个持久性上下文,则为每个持久性上下文实现一个生产者方法,并使用 CDI-Qualifier 对其进行限定。

【讨论】:

  • 我不能使用生产者,因为EntityManager是在运行时创建的
  • 不,问题,然后通过生产者使在运行时创建的 em 可用。 CDI 生产者只是使类型及其实例在定义的限定符的定义范围内对 CDI 可用(默认为@Default),仅此而已。
【解决方案2】:

我是这样解决的:

public class MyBusinessDao {

    private EntityManager em;

    @Inject
    private MyDao myDao;

    private void setEm(EntityManager em){
    this.em = em;
    //and here i call the setEm method of myDao also
    myDao.setEm(em);
    }
    ...

【讨论】:

  • 我认为社区成员对您的解决方案的问题是,您一方面使用 CDI 提供依赖项,另一方面也使用 getter/setter 提供依赖项。这是我不推荐的混淆,因为您与需要提供依赖项的 bean 耦合。每次实现一个新的 bean 时,都需要确保实现来设置 EntityManager。使用 CDI 注入,您只需定义您的依赖项,CDI 将负责提供它。 CDI 的美妙之处在于与 bean 创建和 bean 供应完全分离。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-30
  • 2019-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多