2014-09-30 4 views
2

Я пытаюсь выяснить, как это сделать с CDI. Я работаю над приложением, в котором пользователи могут подключаться к нескольким базам данных. Приложение запрашивает, к которому они хотят подключиться, и они также могут отключиться и подключиться к другой базе данных. Это приложение Java SE, использующее Seam для CDI и Hibernate для JPA. Я пытаюсь выяснить, как использовать CDI для подключения @PersistenceContext, а также сделать его динамическим, чтобы к ним можно было обращаться к различным базам данных. Я просто не уверен, что шаблон или техника я бы использовал для этого с CDI. Мысли?CDI вводят @PersistenceContext на основе ввода пользователем

ответ

2

Так что я думаю, я понял, что я хотел сделать с помощью javax.enterprise.inject.Instance. Сначала определим простой боб:

@Alternative 
public class Foo { 
    private int value; 

    public void setValue(int value) { 
     this.value = value; 
    } 
    public int getValue() { 
     return value; 
    } 
} 

Оно определяется как @Alternative так КДИ не запутаться между этим и метод производителя (показано ниже). Лучшим решением было бы слишком определить Foo в качестве интерфейса, тогда FooImpl будет аннотирован @Typed, поэтому CDI считает, что это только тип bean-типа FooImpl. В любом случае, следующий - класс продюсеров.

@ApplicationScoped 
public class FooProducer { 
    private int value; 
    public FooProducer() { 
     value = -1; 
    } 
    public int getValue() { 
     return value; 
    } 
    public void setValue(int value) { 
     this.value = value; 
    } 
    @Produces 
    public Foo getFoo() { 
     Foo p = new Foo(); 
     p.setValue(getValue()); 
     return p; 
    } 
} 

getFoo() метод создает новый объект Foo с различными значениями. Значение может быть изменено с помощью метода setValue(int). Затем я использую javax.enterprise.inject.Instance для ввода Foo.

@Inject 
Instance<Foo> fooInstance; 

@Inject 
FooProducer fooProducer; 

.... 

fooProducer.setValue(10); 

Foo foo = fooInstance.get(); 
System.out.printf("foo = %s, %d\n", foo.getValue()); 

fooProducer.setValue(10000); 

foo = fooInstance.get(); 
System.out.printf("foo = %s, %d\n", foo.getValue()); 

Здесь я использую впрыскиваемого fooProducer.setValue() способ изменить то, как производитель будет производить Foo. Когда fooInstance.get() называется первый раз Foo будет содержать значение 10, а второй раз, когда он будет иметь значение 10000.

Учитывая этот простой пример, легко применить к получению EntityManager экземпляров к различным базам данных во время выполнения. Есть немного больше кода, который производит EntityManager, но не слишком много.

0

PersistenceContext обрабатывается контейнером EJB. Поскольку вы не находитесь в контейнере EJB, забудьте о контексте сохранения и рассмотрите возможность использования производителей CDI.

@ApplicationScoped 
public class EntityManagerFactoryProvider { 

    private EntityManagerFactory emf; 

    public void voidApplicationEMF() { 
    //load the EMF here based on dynamic properties 
    this.emf = Persistence.createEntityManagerFactpry(Map of loaded properties); 
    } 

    @Produces 
    public EntityManager em() { 
    return emf.createEntityManager(); 
    } 
} 

Тогда где-то в коде

@SessionScoped 
public class MyEntityController { 
    @Inject 
    private EntityManager emf; 
} 

Есть еще вопросы, которые имеют дело с операциями и т.д.

В JSE среде, вы должны явно начать и совершить/отката транзакции. Поскольку вы используете CDI, вы можете использовать Interceptors для запуска/проверки состояния транзакции и отката/фиксации по мере необходимости.

@Interceptor 
public class MyInterceptor { 
    @Inject 
    private EntityManager em; 

    @AroundInvoke 
    public Object intercept(InvocationContext ic) { 
    try { 
     //initiate transaction 
     em.getTransaction().start .... 
     return ic.proceed(); 
    }catch(Exception ex) { //rollback if necessary } 
    finally {//commit transaction if necessary } 
    } 
} 
+0

> 'PersistenceContext обрабатывается контейнером EJB' - это неверно. JPA - отдельная спецификация из EJB, а контекст персистентности обычно задается специфической частью Java EE для реализации JPA. –

+0

@ArjanTijms фактически спецификация JPA является частью спецификации EJB, только выделенный документ разделен – maress

+0

Я не понимаю, как реализовать часть, которую вы комментируете как «// загружаем EMF здесь на основе динамических свойств». Я не хочу класс производителя должен отвечать за пользовательский интерфейс. Я пытаюсь понять путь MVC - представление касается получения динамической информации, а затем передачи ее производителю. Теперь, когда я обдумываю это, пока я печатаю, возможно, события CDI - это путь?Класс продюсера наблюдает за событием и устанавливает динамические данные в классе производителя, используемом при создании EntityManager? Как обновить точки впрыска при изменении базы данных? –

Смежные вопросы