Results 1 to 6 of 6

Thread: Hiberante not using same connection as JDBCTemplate within test

  1. #1
    Join Date
    Jun 2006
    Posts
    13

    Cool Hiberante not using same connection as JDBCTemplate within test

    I have a test that extends AbstractTransactionalDataSourceSpringContextTests, which always fails as hibernate does not use the same connection as the JDBC template.

    The code under test, first uses a JDBC template to perform a query and updates the database accordingly, then a hibernate DAO loads the entities relying on these updates. No commit occurs between the two database calls, hence they both need to use the same connection (database session) for the second to see the updates.

    Debugging, I use the DataSourceUtils.getConnection(ds) at various points to check the connection, this does indeed return the same connection each time proving that there is a transaction. I also use:

    Code:
    SessionFactory sf = (SessionFactory) applicationContext.getBean("sessionFactory");
    Connection c1 = DataSourceUtils.getConnection(SessionFactoryUtils.getDataSource(sf));
    to check the connection from the hibernate session factory. This also returns the same connection.

    But when I debug right into the hibernate code the connection used is a different one, it seems that is is got straight from the datasouce, hence no updates are seen and the test fails.

    Below is stack trace of where hibernate opens the connection (if it helps).
    Code:
    LocalDataSourceConnectionProvider.getConnection() line: 81	
    ConnectionManager.openConnection() line: 423	
    ConnectionManager.getConnection() line: 144	
    BatchingBatcher(AbstractBatcher).prepareQueryStatement(String, boolean, ScrollMode) line: 139	
    CriteriaLoader(Loader).prepareQueryStatement(QueryParameters, boolean, SessionImplementor) line: 1547	
    CriteriaLoader(Loader).doQuery(SessionImplementor, QueryParameters, boolean) line: 673	
    CriteriaLoader(Loader).doQueryAndInitializeNonLazyCollections(SessionImplementor, QueryParameters, boolean) line: 236	
    CriteriaLoader(Loader).doList(SessionImplementor, QueryParameters) line: 2220	
    CriteriaLoader(Loader).listIgnoreQueryCache(SessionImplementor, QueryParameters) line: 2104	
    CriteriaLoader(Loader).list(SessionImplementor, QueryParameters, Set, Type[]) line: 2099	
    CriteriaLoader.list(SessionImplementor) line: 94	
    SessionImpl.list(CriteriaImpl) line: 1569	
    CriteriaImpl.list() line: 283	
    HibernateTemplate$35.doInHibernate(Session) line: 991	
    HibernateTemplate.execute(HibernateCallback, boolean) line: 373	
    HibernateTemplate.findByCriteria(DetachedCriteria, int, int) line: 981	
    HibOperationDAO(HibernateEntitySelector).findByQuery(PagedPVO, String, Object[]) line: 103
    When I perform a similar test when running within the application server there is no problem. The application server uses JTS transactions.
    So I am guessing that for some reason hibernate is not getting the connection that is already associated to the transaction. But while I was debugging the code the hibernate template says there is an existing transaction (stack trace: HibernateTemplate.execute(HibernateCallback, boolean) line: 364)

    I'm sure there is just some configuration of the test that I am not doing.

    Can anyone help?
    Cheers.

  2. #2
    Join Date
    Sep 2004
    Posts
    1,086

    Default

    Can you post your datasource/transactionmanager config?

  3. #3
    Join Date
    Jun 2006
    Posts
    13

    Default

    Thanks for your interest.

    The datasouce is:
    Code:
    <bean id="opusDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close">
      <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
      <property name="url" value="URL" />
      <property name="username" value="user" />
      <property name="password" value="pass" />
    </bean>
    The test transaction manager is:
    Code:
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource">
        <ref bean="opusDataSource" />
      </property>
    </bean>
    Now I have managed to get the tests to pass by using a HibernateTransactionManager, which requires the session factory to be injected. Now I can have two different transaction managers, one for where there is a session factory and one where there isn't. This seems unnecessary though.

    So why is the JDBC template compatible with the HibernateTransactionManager but the hibernate template not with the DataSourceTransactionManager. Especially since the session factory is configured with a datasource.

    Thanks again

  4. #4
    Join Date
    Sep 2004
    Posts
    1,086

    Default

    Because datasource can be extracted from the sessionfactory but sessionfactory can't be extracted from the datasource.

  5. #5
    Join Date
    Jun 2006
    Posts
    13

    Default

    I can see that, just seems odd that Hibernate needs to sync the transaction to the session factory rather than the datasource. As the connection has ultimately got to come from the datasource. Especially since it works fine when using the JTA transaction manager.

    I'm sure I'm over simplifying this, but a quick explanation would be appreciated.

  6. #6
    Join Date
    Sep 2004
    Posts
    1,086

    Default

    In order to manage hibernate transactions, Spring needs to bind the session to the thread, not connection.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •