Как использовать разные EntityManager в зависимости от условий во время выполнения? - PullRequest
0 голосов
/ 05 марта 2019

Моя конфигурация похожа на приведенную ниже:

Абстрактный класс:

public abstract class AbstractFacade<T> {

    private Class<T> entityClass;

    public AbstractFacade(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    protected abstract EntityManager getEntityManager();

    public T find(Object id) {
        return getEntityManager().find(entityClass, id);
    }

    // other methods create(T), edit(T), ...

Ejb, расширяющий абстрактный класс (у меня есть много других EJB и около 12 различных единиц персистентности):

@Stateless
public class FilesDao extends AbstractFacade<Files> {

    @PersistenceContext(unitName = "myfirstPU")
    private EntityManager firstEm;

    @PersistenceContext(unitName = "mysecondPU")
    private EntityManager secondEm;

    // i have more than two persistenceUnit ... 

    @Override
    protected EntityManager getEntityManager() {
         return firstEm; // or secondEm based on condition
    }

    public FilesDao() {
         super(Files.class);
    }

    public Files findByFileref(String inFileRef) {
         try {
             Query q = firstEm.createNamedQuery("Files.findByFileref"); // or secondEm based on condition
             q.setParameter("fileref", inFileRef);
             Files file = (Files) q.getSingleResult();
             return file;
        } catch (NoResultException e) {
             return null;
        }
    }

Я хочу использовать FilesDao следующим образом:

@Stateless
@LocalBean
public class FileBusiness {

    @EJB
    FilesDao fileDao;

    public void myMethod(){
    if(condition1){
         //use the FileDao with the EnityManager **firstEm**
    }
    else if(condition2){
        //use the FileDao with the EnityManager **secondtEm**
    }
    ...

}

Есть ли способ достичь этого?

Я читал об использовании CDI с методом метаданных.

1 Ответ

0 голосов
/ 30 марта 2019

Производители CDI не так сложны, см. Следующий пример.

Следующие классы являются аннотациями CDI-Qualifier, которые используются для различения реализаций.

@Retention(RetentionPolicy.RUNTIME)
@Target({ TYPE, METHOD, FIELD, PARAMETER, CONSTRUCTOR }) 
@Qualifier 
public @interface MyfirstPUQualifier {  }

@Retention(RetentionPolicy.RUNTIME)
@Target({ TYPE, METHOD, FIELD, PARAMETER, CONSTRUCTOR }) 
@Qualifier 
public @interface MysecondPUQualifier {  }

bean-компонент CDI, который внедряет различные EntityManager и реализует методы производителя, делая два EntityManager доступными для CDI, различаемых с помощью CDI-Qualifiers

@ApplicationScoped
class MYProducer {
    @PersistenceContext(unitName = "myfirstPU")
    private EntityManager firstEm;

    @PersistenceContext(unitName = "mysecondPU")
    private EntityManager secondEm;

    @Produces
    @RequestScoped
    @MyfirstPUQualifier
    public EntityManager produceMyfirstPU(){
        return firstEm;
    }


    @Produces
    @RequestScoped
    @MysecondPUQualifier
    public EntityManager produceMysecondPU(){
        return secondEm;
    }
}

Ниже показан CDI-бин, внедряющий оба EntityManager.Это может быть извлечено в абстрактный базовый класс, потому что может быть необходимо и другим DAO.

@Stateless
public class FileDao {

    @Inject
    @MyfirstPUQualifier
    private EntityManager emFirst;

    @Inject
    @MysecondPUQualifier
    private EntityManager emSecond;

    public void myDaoMEthod(){
        final EntityManager em = getEntityManager();
        ...
    }

    private EntityManager getEntityManager(){
        if(condition1){
            return emFirst;
        }
        else if(condition2){
            return emSecond;
        }
    }
}

Нет, нельзя использовать bean-компонент FileDao, не заботясь о том, какой EntityManager использовать, потому что в этом не следует принимать решениебоб в любом случае

@Stateless
@LocalBean
public class FileBusiness {

    @EJB
    FilesDao fileDao;

    public void myMethod(){
        // FileDao will decide what entity manager to use
        fileDao.doStruff();
    }
}
...