Динамический атрибут @PersistenceContext unitName для контейнерного EntityManager

в основном, что я хочу сделать, это присвоить атрибуту unitName " @PersistenceContext со значением, которое я получу из сеанса во время выполнения.

в деталях;

мое приложение будет SaaS-приложением, и у меня будут отдельные БД для каждого другого арендатора. Я использую Glassfishv3 и управляю сущностями на основе контейнеров, поэтому я не получаю никакого экземпляра из EntityManagerFactory явно. Все, что я делаю для создания диспетчера сущностей:

@PersistenceContext(unitName = "DBNAME")
private EntityManager entityManager;

Мне нужно передать атрибут unitName в соответствии с текущим пользователем. он не должен быть жестко закодирован.

Я обновил Eclipselink 2.3, но все примеры создают экземпляр из EMF, который вы можете передать свойство Map, как

Map memberProps = new HashMap();
memberProps.put("memberPu1", props1);
memberProps.put("memberPu2", props2);

Map props = new HashMap();
props.put("eclipselink.jdbc.exclusive-connection.mode", "Always");
props.put("eclipselink.composite-unit.properties", memberProps);

EntityManager em = emf.createEntityManager(props);

маловероятно в моем приложении, контейнер выполняет эту работу, поэтому я не могу этого сделать

EntityManager em = emf.createEntityManager(props);

Несмотря на то, что у меня есть все единицы и классы персистентности в моем persistence.xml с использованием определений JNDI, я не могу сообщить серверу приложений, какая БД (единица непрерывности) она должна использовать на время

любая помощь будет оценена

Ответ 1

Значения аннотаций не могут быть назначены во время выполнения, поэтому вам нужно будет найти стратегию, в которой вы можете создать несколько PersistenceContext s. Если вы можете использовать CDI, это, вероятно, упростит вашу жизнь.

С CDI вы можете создать производителя следующим образом:

public class EntityManagerProducer {

  @PersistenceContext(unitName="firstUnit") private EntityManager firstEntityManager;
  @PersistenceContext(unitName="secondUnit") private EntityManager secondEntityManager;

  @Produces
  public EntityManager getEntityManager(InjectionPoint injectionPoint) {
     if(<your_first_criteria>) {
       return firstEntityManager;
     } else if (<your_second_criteria>) {
       return secondEntityManager;
     }
  }

Затем вы можете использовать свой метод производителя, например. ваш DAO:

@Inject private EntityManager entityManager;

EDIT: Я бы, вероятно, рекомендовал использовать аннотацию @Qualifier, поскольку она дает понять, откуда вы получаете EntityManager.

Ответ 2

Вам нужно использовать управляемый приложением ресурс, а не контейнер.

то есть. Persistence.createEntityManagerFactory()

Вы все еще можете использовать JTA, а не инъекцию.