Announcement Announcement Module
Collapse
No announcement yet.
Hiberante not using same connection as JDBCTemplate within test Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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
    Can you post your datasource/transactionmanager config?

    Comment


    • #3
      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

      Comment


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

        Comment


        • #5
          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.

          Comment


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

            Comment

            Working...
            X