Mixing and Matching Spring JdbcTemplate and HibernateTemplate
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
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
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
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
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.