I have a complex situation where I have to use 2 different databases, there for I use 2 different transaction managers. Is there a way in Spring to link these transaction managers to work in a single transaction ? In case of an exception on the second dataSource changes on the first should be rolled-back.
<bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
abstract="true">
<property name="transactionManager" ref="transactionManager" />
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@dummyHost:1521:dummySID" />
<property name="username" value="owner" />
<property name="password" value="password" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@dummyHost2:1521:dummySID2" />
<property name="username" value="owner" />
<property name="password" value="password" />
</bean>
<bean id="transactionManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource2" />
</bean>
You just need to create two transaction managers and inject them with the appropriate connection. But I must ask the question: why do you think you need two transaction managers? You can have more than one database connection.
If you call a method with a @Transactional annotation from a method with @Transactional within the same instance, then the called methods transactional behavior will not have any impact on the transaction.
Nested transactions in Spring are just JDBC / database savepoints. If you don't know what a savepoint is, have a look at this tutorial, for example. Note that savepoint support is dependent on your JDBC driver/database.
If one of those sub-units encounters a problem (runtime exception by default) then the nested transaction will roll back internally through something called savepoints but the top level transaction will be allowed to continue.
You can use Spring's JtaTransactionManager to make sure both DBs are transacted with a single transaction manager.
Note, you would have to choose an underlying implementation which can either be a container's one: e.g. WebLogic, WebSphere and OC4J, etc.. or a stand alone, even an open source one: e.g. Atomikos.
XA transaction management complicates things (configuration / performance / problem resolution / maintenance / etc.). And in a lot of cases, it can be avoided by clever patterns.
To get a solid understanding on whether you need to use XA ( e.g. distributed ) transaction manager, take a look at this fantastic article by Spring's own Dave Syer: Distributed transactions in Spring, with and without XA
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With