hossein shemshadi
hossein shemshadi

Reputation: 303

Using multiple transaction managers with hibernate-spring integration (annotation-based)

I am working on a project which needs to connect to one database of oracle and read some data from tables and then after summarizing the data puts them in a second database of mysql.

I need to use transaction managers for this project. So I did something like the below:

spring-application-context.xml

<tx:annotation-driven transaction-manager="oracleTransactionManager" proxy-target-class="true"/>

<bean id="oracleTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="oracleSessionFactory"/>
    <qualifier value="oracleTransactionManager"/>
</bean>

<bean id="mysqlTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="mysqlSessionFactory"/>
    <qualifier value="mysqlTransactionManager"/>
</bean>

MysqlService.java

@Transactional
@Qualifier("mysqlTransactionManager")
public class MysqlService{
    public void saveAll(List<myEntity> myEntities) {
        List<BaseEntity> baseEntities = (List<BaseEntity>) (List<?>) myEntities; 
        myEntitiyDAO.saveAll(baseEntities);
    }
}

But the problem is when I run this code I get the below errors:

Exception in thread "Thread-3" org.hibernate.HibernateException: persist is not valid without active transaction
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:341)
at com.sun.proxy.$Proxy11.persist(Unknown Source)
at com.peykasa.sdp.messagesummerizer.datamodel.smsbox.dao.MysqlTaskMessageDAOImpl.save(MysqlTaskMessageDAOImpl.java:28)
at com.peykasa.sdp.messagesummerizer.datamodel.mysql.service.MysqlTaskMessageService.saveAll(MysqlTaskMessageService.java:35)
at com.peykasa.sdp.messagesummerizer.datamodel.mysql.service.MysqlTaskMessageService$$FastClassBySpringCGLIB$$894181ef.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:708)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)
at com.peykasa.sdp.messagesummerizer.datamodel.mysql.service.MysqlTaskMessageService$$EnhancerBySpringCGLIB$$c16175a6.saveAll(<generated>)
at com.peykasa.sdp.messagesummerizer.lifecycle.DataSummarizerThread.run(DataSummarizerThread.java:66)

Why this error occurs and how can I fix it?

I've used spring 4.0.5 and hibernate 3.6.10.

Thanks in advance,

Upvotes: 2

Views: 2393

Answers (1)

Gary Russell
Gary Russell

Reputation: 174759

The transaction manager goes on @Transactional not @Qualifier.

@Transactional("mysqlTransactionManager")

See the docs.

EDIT

I just ran a test with two separate transaction managers (not using hibernate though) and it works fine, as expected.

Is your MySqlService defined as a <bean/>? Spring can only start a transaction if it manages the object instance.

Turn on TRACE level logging for org.springframework.transaction to get detailed logging. This is what I see when calling 2 beans; one using the default tx manager; the other using an explicit one...

09:39:37.528 TRACE [main][org.springframework.transaction.support.TransactionSynchronizationManager] Initializing transaction synchronization
09:39:37.529 TRACE [main][org.springframework.transaction.interceptor.TransactionInterceptor] Getting transaction for [org.springframework.integration.samples.jdbc.Foo.doIt]
09:39:37.529 TRACE [main][org.springframework.transaction.interceptor.TransactionInterceptor] Completing transaction for [org.springframework.integration.samples.jdbc.Foo.doIt]
09:39:37.530 TRACE [main][org.springframework.transaction.support.TransactionSynchronizationManager] Clearing transaction synchronization
09:39:40.700 TRACE [main][org.springframework.transaction.support.TransactionSynchronizationManager] Initializing transaction synchronization
09:39:40.700 TRACE [main][org.springframework.transaction.interceptor.TransactionInterceptor] Getting transaction for [org.springframework.integration.samples.jdbc.Bar.doIt]
09:39:40.700 TRACE [main][org.springframework.transaction.interceptor.TransactionInterceptor] Completing transaction for [org.springframework.integration.samples.jdbc.Bar.doIt]
09:39:40.701 TRACE [main][org.springframework.transaction.support.TransactionSynchronizationManager] Clearing transaction synchronization

I can tell in the debugger that each uses the correct tx manager.

Upvotes: 3

Related Questions