如何控制客户端的CMT注入?

How to control CMT injection from clients?

假设我有一个 EJB。

@Stateless
public class PersistenceService {

    @PersistenceContext(unitName="dependent")
    private transient EntityManager entityManager;
}

有什么方法可以控制客户端的 unitName 值吗?

@RequestScoped
@Path("/persistence")
public class PersistenceResource {

    //"some"
    @Inject
    private transient PersistenceService somePU;

    //"other"
    @Inject
    private transient PersistenceService otherPU;
}

1) 为您的 PU 创建 2 个 CDI qualifiers

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
public @interface SomePC {
}

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
public @interface OtherPC {
}

2) 然后将您的 PU 公开为 CDI bean

@ApplicationScoped
public class EntityManagerProducer {


@Produces
@PersistenceContext(unitName = "somePU")
@SomePC
private EntityManager em;

@Produces
@PersistenceContext(unitName = "otherPU")
@OtherPC
private EntityManager em;
}

3) 在您的服务中注入两个 EM:

@Stateless
public class PersistenceService {

    @Inject 
    @SomePC
    private emSome;

    @Inject 
    @OtherPC
    private emOther;

    public SeomthingUseful doSomething(Context myContext){
      getEntityManager(myContext);
      ... 
    }   

    private EntityManager getEntityManager(Context myContext){
      if(myContext == SOME_PU)
        return emSome;
      return emOther;
    }
}

4) 从您的客户端,您可以将上下文传递给 select 适当的 PU(您也可以为此目的创建一个 RequestScoped bean,在这种情况下您不必使用方法参数):

@RequestScoped
@Path("/persistence")
public class PersistenceResource {

   @Inject
   PersistenceService service;

   public void myMethod(){
      service.doSomething(myContext.SOME_PU);
   }


}

上下文可以是具有您需要的不同值的枚举 (SOME_PU、OTHER_PU)。作为替代方案,您可以通过执行以下操作在您的服务中动态注入所有 EMs bean:

@Inject @Any Instance<EntityManager> emSource;

如果你遵循这条路,那么一切都会得到解释here