Создайте Entitymanager с расширенным контекстом персистентности через CDI

Мы пытаемся построить систему, которая «производит» entitymanager в зависимости от вошедшего в систему пользователя (своего рода мультиарендность). Поэтому мы реализовали 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 без сохранения состояния с менеджером транзакций?


person Primi    schedule 17.10.2012    source источник
comment
Я не понимаю проблемы. Уточните, в чем конкретно проблема. Например, опубликованный код работает или нет? Можете ли вы вставить код, который не работает?   -  person Karl Kildén    schedule 17.10.2012
comment
Да, мой код работает до тех пор, пока entitymanager внедряется в ejbs без сохранения состояния. Но что я могу сделать, если мне нужен менеджер сущностей в ejb с отслеживанием состояния (с аннотацией @PersistenceContext(type = PersistenceContextType.EXTENDED)? Я также пытался создать метод производителя для этого, но я думаю, что жизненный цикл CDI отличается от EJB жизненного цикла, поэтому я либо всегда получаю новый менеджер сущностей (@RequestScoped), либо всегда получаю один и тот же менеджер сущностей (@SessionScoped - это приводит к исключению, поскольку em уже привязан). К сожалению, ваше предложение ниже не помогает мне в этом случае .   -  person Primi    schedule 18.10.2012


Ответы (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;

Конечно, вы можете использовать квалификатор, чтобы различать фабрики, вместо того, чтобы проверять имя поля. Я просто хотел получить более глубокий ответ.

person Karl Kildén    schedule 17.10.2012
comment
Осторожно с заводами! Вы получите от них менеджер сущностей управляемый приложением, который отличается от управляемого контейнером тем, что вам нужно позаботиться об административных задачах, таких как их закрытие. - person Mike Braun; 18.10.2012