Skip to content

Mixing and Matching Spring JdbcTemplate and HibernateTemplate

published: 

The JdbcTemplate and HibernateTemplate convenience classes from Spring really make working with the respective APIs a breeze. Unfortunately getting both of these classes to work together within a single Transaction is not straightforward. This comes up very frequently in JUnit tests where you want to verify Hibernate is working with the database in the way you expect, either by inserting data and letting Hibernate load it or by checking to see that Hibernate creates the data you expect. The same will hold true in application code where you need to add JDBC code alongside Hibernate code to meet various requirements. The testing scenarios are simple and illustrative so let’s explore those.

One common use case is to persist an object with HibernateTemplate and then verify the data was inserted correctly using JdbcTemplate. Usually Hibernate will not flush the data out to the DB until the transaction commits, meaning that the query done by JdbcTemplate won’t be able to see the new data. This one isn’t hard to work around: just call HibernateTemplate.flush() to execute the SQL on demand so that subsequent calls to JdbcTemplate will see the new data.

The second use case is a lot tricker: let’s say you want to create some data with JdbcTemplate and then make sure that calls to HibernateTemplate will see that data. By default this will not work. You can actually insert with JdbcTemplate, make a call to load the data with HibernateTemplate (it won’t find it) and then make another call to JdbcTemplate which will show that the data is there. The problem is that since JdbcTemplate is injected with a DataSource it doesn’t really have any knowledge of the transactions from HibernateTransactionManager; thus operations from the two templates are isolated from one another.

Fortunately Spring offers a solution in the TransactionAwareDataSourceProxy class. Just like the name imples, this class acts as a wrapper for an existing DataSource so that all collaborators will participate in Spring-managed transactions. Configuration of this class is trivial:

<bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
    <property name="targetDataSource">
        <bean class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">...</bean>
    </property>
</bean>

Note: you may or may not want to define the “real” DataSource as an inner bean that doesn’t get registered in the ApplicationContext itself. If you are autowiring your DataSource purely by type, having two different implementations of DataSource will be a problem for you. Workarounds include autowiring using @Qualifier or using @Resource to inject the bean by name.


tags: