Edit: I had problems with the configuration in this post but I was able to fix it. The problem is when I tried to make a two-phase commit the second transaction didn't begin with annotation based transaction management. But I was able to make a two-phase commit by using programmatic transaction management with second transaction. That means adding below code to the service where second transaction is started. I thing to use transactions with different databases JTA transact.on management should be used.
@Qualifier("txManager2")
@Autowired
private PlatformTransactionManager transactionManager;
...
...
...
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);
try {
doSomething();
}
catch (Exception ex) {
transactionManager.rollback(status);
throw ex;
}
transactionManager.commit(status);
Recently, I needed to add a second database connection to the project I currently develop for. After searching through the internet I had some ideas in my head but I couldn't not find an exact solution. After a bit struggling, I found a fairly easy solution. At first in ApplicationContext.xml of the project, there was one data source and one session factory which is created with this data source. There was an abstract hibernate dao which is created with this session factory. All dao classes in the project is a subclass of this class. I created a second abstract hibernate class and use this class as parent class for dao classes of new database. Of course I needed a second session factory to create this class so I added a new session factory to ApplicationContext.xml. In order to inject right session factory to rigth abstract hibernate class I added @Qualifier annotation followed by session factory name to the session factory setter methods of abstract hibernate classes. And of course I added a second data source to ApplicationContext.xml to be used by new session factory. After doing these, the only problem was transaction management and it has also a fairly easy solution. I added a second transaction manager to ApplicationContext.xml to be used with the new session factory.
Now, after all these work, the system has the ability to work with two different databases. I put the resulting classes and ApplicationContext.xml below.
ApplicationContext.xml
....
....
....
<bean id="txManager1" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory1" />
</bean>
<bean id="sessionFactory1" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource1" />
....
....
....
</bean>
<bean id="dataSource1" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
....
....
....
</bean>
<bean id="sessionFactory2" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource2" />
....
....
....
</bean>
<bean id="dataSource2" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
....
....
....
</bean>
<bean id="txManager2" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory2" />
</bean>
....
....
....
AbstractHibernateDAO1
public abstract class AbstractHibernateDAO1 {
....
....
....
protected HibernateTemplate hibernateTemplate;
@Autowired
@Qualifier("sessionFactory1")
public void setHibernateTemplate(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
....
....
....
}
AbstractHibernateDAO2
public abstract class AbstractHibernateDAO2 {
....
....
....
protected HibernateTemplate hibernateTemplate;
@Autowired
@Qualifier("sessionFactory2")
public void setHibernateTemplate(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
....
....
....
}