Dear all,
Is it possible use JTA(JOTM) to let HibernateTemplate and JdbcTemplate share the same database connection ? I have tried to configure JtaTransactionManager with HibernateIntercetor, but it does not work... below is my test configuration:
applicationContext.xml
CheckSameConnection and CheckSameConnectionImpl are simpleCode:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean" /> <bean id="innerDataSource" class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"> <property name="transactionManager"> <ref local="jotm" /> </property> <property name="driverName"> <value>oracle.jdbc.driver.OracleDriver</value> </property> <property name="url"> <value> jdbc:oracle:thin:@abcd.bioinfo:1521:ABCD </value> </property> </bean> <bean id="dataSource" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"> <property name="dataSource"> <ref local="innerDataSource" /> </property> <property name="user"> <value>abcd</value> </property> <property name="password"> <value>abcd</value> </property> <property name="maxSize"> <value>30</value> </property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="mappingDirectoryLocations"> <list> <value>classpath:/antar/</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.dialect"> org.hibernate.dialect.Oracle9Dialect </prop> </props> </property> <property name="jtaTransactionManager"> <ref bean="jotm" /> </property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource"> <ref local="dataSource" /> </property> </bean> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory"> <ref bean="sessionFactory" /> </property> </bean> <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="userTransaction"> <ref local="jotm" /> </property> </bean> <bean id="checkSameConnection" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"> <ref local="transactionManager" /> </property> <property name="target"> <bean class="antar.config.CheckSameConnectionImpl"> <property name="hibernateTemplate"> <ref bean="hibernateTemplate" /> </property> <property name="jdbcTemplate"> <ref bean="jdbcTemplate" /> </property> </bean> </property> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> <property name="postInterceptors"> <list> <bean class="org.springframework.orm.hibernate3.HibernateInterceptor"> <property name="sessionFactory"> <ref bean="sessionFactory" /> </property> </bean> </list> </property> </bean> </beans>
classes and wrapped by transaction. CheckSameConnectionImpl inject HibernateTemplate and JdbcTemplate to check whether the connection is shared.
finally, a simple test case to invoke a transaction wrapped checkSameConnection bean:Code:public interface CheckSameConnection { public void doTransaction(); } public class CheckSameConnectionImpl implements CheckSameConnection { private HibernateTemplate hibernateTemplate; private JdbcTemplate jdbcTemplate; public void doTransaction() { final XAPoolNativeJdbcExtractor extractor = new XAPoolNativeJdbcExtractor() ; System.out.println("begin... "); hibernateTemplate.execute(new HibernateCallback() { public Object doInHibernate(final Session session) throws HibernateException, SQLException { final Connection connFromHibernate = session.connection() ; jdbcTemplate.execute(new ConnectionCallback() { public Object doInConnection(final Connection connFromJdbc) throws SQLException, DataAccessException { Connection ch = extractor.getNativeConnection(connFromHibernate) ; Connection cj = extractor.getNativeConnection(connFromJdbc) ; if( cj== ch) { System.out.println("same connection"); } else { System.err.println("not same connection:" + cj +" != " + ch); } return null; } }); return null; } }); System.out.println("done..."); } }
and the debug output isCode:public class HibernateJDBCConnectionTest extends AbstractDependencyInjectionSpringContextTests { protected String[] getConfigLocations() { return new String[] {"/applicationContext-jta.xml"} ; } public void testSameConnectionWithSameTransactionManager() { CheckSameConnection csc = (CheckSameConnection) applicationContext .getBean("checkSameConnection"); csc.doTransaction(); } }
the result shows that TransactionManager and HibernateInterceptor work correctly, however, the connection used by HibernateTemplate is not the same as the one used by JdbcTemplate...Code:DEBUG AbstractPlatformTransactionManager - Using transaction object [org.springframework.transaction.jta.JtaTransactionObject@2b3483] DEBUG AbstractPlatformTransactionManager - Creating new transaction DEBUG JtaTransactionManager - Beginning JTA transaction DEBUG TransactionSynchronizationManager - Initializing transaction synchronization DEBUG SessionFactoryUtils - Opening Hibernate session DEBUG SessionFactoryUtils - Registering Spring transaction synchronization for new Hibernate session DEBUG TransactionSynchronizationManager - Bound value [org.springframework.orm.hibernate3.SessionHolder@46c21b] for key [org.hibernate.impl.SessionFactoryImpl@c701cb] to thread [main] DEBUG HibernateInterceptor - Found thread-bound session for Hibernate interceptor begin... DEBUG TransactionSynchronizationManager - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@46c21b] for key [org.hibernate.impl.SessionFactoryImpl@c701cb] bound to thread [main] DEBUG TransactionSynchronizationManager - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@46c21b] for key [org.hibernate.impl.SessionFactoryImpl@c701cb] bound to thread [main] DEBUG TransactionSynchronizationManager - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@59e40] for key [StandardXAPoolDataSource: ... **cut** not same connection:oracle.jdbc.driver.T4CConnection@74641 != oracle.jdbc.driver.T4CConnection@d59861 DEBUG TransactionSynchronizationManager - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@59e40] for key [StandardXAPoolDataSource: ... **cut** DEBUG TransactionSynchronizationManager - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@46c21b] for key [org.hibernate.impl.SessionFactoryImpl@c701cb] bound to thread [main] done... DEBUG HibernateInterceptor - Not closing pre-bound Hibernate session after interceptor DEBUG AbstractPlatformTransactionManager - Triggering beforeCommit synchronization DEBUG AbstractPlatformTransactionManager - Triggering beforeCompletion synchronization DEBUG TransactionSynchronizationManager - Removed value [org.springframework.orm.hibernate3.SessionHolder@46c21b] for key [org.hibernate.impl.SessionFactoryImpl@c701cb] from thread [main] DEBUG SessionFactoryUtils - Closing Hibernate session DEBUG TransactionSynchronizationManager - Removed value [org.springframework.jdbc.datasource.ConnectionHolder@59e40] for key [StandardXAPoolDataSource: ... **cut** DEBUG AbstractPlatformTransactionManager - Initiating transaction commit DEBUG JtaTransactionManager - Committing JTA transaction DEBUG AbstractPlatformTransactionManager - Triggering afterCompletion synchronization DEBUG TransactionSynchronizationManager - Clearing transaction synchronization
Do I missing something ?
ps. Spring - 1.2rc1
Hibernate - 3.0rc1


Reply With Quote