First of all, thanks to user332768 and bert. I tried using AbstractRoutingDataSource, as mentioned in the link provided by bert, but got lost trying to connect my jpa (eclipselink) layer. I returned to my earlier approach with some changes. The solution looks cleaner (IMHO) and works fine. (switching the database at runtime, as well as writing to multiple databases in one transaction)
public class MyEntityManagerFactoryImpl implements MyEntityManagerFactory, ApplicationContextAware { private HashMap<String, EntityManagerFactory> emFactoryMap; public EntityManager getEntityManager(String releaseId) { return SharedEntityManagerCreator.createSharedEntityManager(emFactoryMap.get(releaseName)); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { Map<String, LocalContainerEntityManagerFactoryBean> emMap = applicationContext.getBeansOfType(LocalContainerEntityManagerFactoryBean.class); Set<String> keys = emMap.keySet(); EntityManagerFactory entityManagerFactory = null; String releaseId = null; emFactoryMap = new HashMap<String, EntityManagerFactory>(); for (String key:keys) { releaseId = key.split("_")[1]; entityManagerFactory = emMap.get(key).getObject(); emFactoryMap.put(releaseId, entityManagerFactory); } } }
Now I insert my DAO with an instance (singleton) of MyEntityManagerFactoryImpl. Then dao will simply call createSharedEntityManager with the required release and get the correct EntityManager for this database. (Note that now I am using the application-driven EntityManager and therefore I must explicitly close them in my dao)
I also went to jta transaction manager (to manage transactions across multiple databases) Here is what my spring xml looks like.
... <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="em_Rel1"> <property name="persistenceUnitName" value="PU1" /> </bean> <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="em_Rel2"> <property name="persistenceUnitName" value="PU2" /> </bean> <bean class="org.springframework.transaction.jta.JtaTransactionManager" id="jtaTransactionManager"> </bean> <tx:annotation-driven transaction-manager="jtaTransactionManager"/> ....
Hurrah! (comments are welcome)
source share