2014-09-19 8 views
2

Я боролся с этой проблемой в течение нескольких дней,Управление несколькими базами данных Соединения

Вот сценарий: У меня есть несколько баз данных, один для каждого из моих клиентов, все с той же структуры (то же самое таблицы и столбцы), поэтому мое приложение должно решить во время выполнения, с которым ему нужно подключиться. Я использую JPA2, EclipseLink и EJB3.

Моя первая попытка состояла в том, чтобы реализовать пользовательский EntityManager со всей логикой для выполнения операций с правой базой данных, затем я сконфигурировал этот EntityManager как EBate без учета состояния, чтобы сделать возможным его добавление с помощью аннотации @EBJ (как описано по этой ссылке: http://www.hostettler.net/blog/2012/11/20/multi-tenancy/). Я не заставляю его работать, потому что он бросает исключение, пытаясь внедрить EntityManager.

Так что я решил попробовать что-то другое, я создал EntityManagerFactory и я передал JTA_DATASOURCE к нему (после того, как решить, во время выполнения, один для использования), поэтому он может подключиться к базе данных правой .

Вот код:

@Stateless 
@TransactionManagement(TransactionManagementType.CONTAINER) 
public class TestEntDAO { 

    private EntityManager em; 
    private EntityManagerFactory emf; 

    @PostConstruct 
    public void init() { 
     em = getEntityManager(); 
    } 

    public EntityManager getEntityManager() { 
     Map props = new HashMap(); 
     props.put(PersistenceUnitProperties.TRANSACTION_TYPE, "JTA"); 
     props.put(PersistenceUnitProperties.JTA_DATASOURCE, dataSourceName()); 
     emf = Persistence.createEntityManagerFactory("testePU", props); 
     em = emf.createEntityManager(); 
     return em; 
    } 

    public String dataSourceName(){ 
     if(someCondition){ 
      return "db1"; 
     }else{ 
      return "db2"; 
     } 
    } 
} 

Это работало отлично, единственная проблема заключается в том, что сделка не управляется контейнера, так что я должен был явно отметить границы сделки (называют начать() и commit()). Я мог бы просто использовать аннотацию @PersistenceContext, чтобы она работала, но тогда у меня не было бы EntityManagerFactory для передачи источника данных.

Кто-нибудь знает, как использовать Транзакции, управляемые контейнером (CMT), и все еще иметь возможность передавать данные?

+0

Почему вы не можете вводить имя источника данных? Или прочитать его из файла свойств? –

+0

Я просто не мог найти способ сделать это и использовать @PersistenceContext в то же время –

ответ

0

Возможно, попробуйте определить 3 источника данных и 3 единицы сохранения.

<persistence-unit name="PU1"> 
    <jta-data-source>jdbc/DS1</jta-data-source> 
    ... 
</persistence-unit> 
<persistence-unit name="PU2"> 
    <jta-data-source>jdbc/DS2</jta-data-source> 
    ... 
</persistence-unit> 
<persistence-unit name="PU3"> 
    <jta-data-source>jdbc/DS3</jta-data-source> 
    ... 
</persistence-unit> 

И вводить диспетчер сущности из любой единицы, требующей сохранения.

@PersistenceContext(unitName = "PU2") 
EntityManager em; 

Это должно работать, хотя я не тестировал его.

+0

Я уже пробовал это, он работал, но если одно из соединений не удалось, приложение не будет развертываться. –

+0

Может быть, это можно преодолеть. Какая у вас ошибка? – zbig

+0

Что-то вроде этого -> Внутреннее исключение: java.sql.SQLException: ошибка при распределении соединения. Причина. Соединение не может быть выделено, потому что: попытка подключения не удалась. –

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