i have legacy code the uses an db-access layer that is implemented in plain jdbc. this layer is going to be substituted by aspring manageg mixed hibernate, jdbc layer.
i have one pooled datasource, a hibernate session factory and a hibernateTransaction Manager defined in my applicationContext.xml:
Code:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
....
</bean>
<!-- Hibernate Session Factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingDirectoryLocations">
<list>
<value>classpath:...</value>
</list>
</property>
<property name="hibernateProperties">
...
</property>
</bean>
<!-- Hibernate Transaction Manager -->
<bean id="txManagerHibernate" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
legacy code looks like this (where db is the db-access layer):
Code:
db.connect();
// access dataSource with jdbcTemplate or hibernateTemplate (CRUD):
db.execute("INSERT ....");
db.delete(entity);
// and so on (any combination possible
db.commit();
db.rollback(); // on exception
db.disConnect(); // finally
between rollback or commit the db class tries to manage the transaction under the hood. in the new version i designed it like AbstractTransactionalDataSourceSpringContextTests.
commit/rollback now works! i've tried with several things. with the newest combination it WORKS all of a sudden. => so far ok
here is some code from the db class (excerpt)
Code:
public void connect() throws Exception {
transactionDefinition = new DefaultTransactionDefinition();
}
public void rollback() throws SQLException {
/**
* this works for jdbc:
*/
Connection conn = DataSourceUtils.getConnection((DataSource)
Spring.getFactory().getBean("dataSource"));
conn.rollback();
/**
* this for hibernate:
*/
this.transactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
this.transactionStatus = hibernateTransactionManager.getTransaction(this.transactionDefinition);
hibernateTransactionManager.rollback(transactionStatus);
}
public void disConnect() throws SQLException {
transactionDefinition = null;
}
public void commit() throws SQLException {
hibernateTransactionManager.commit(this.transactionStatus);
this.transactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
this.transactionStatus = hibernateTransactionManager.getTransaction(this.transactionDefinition);
}
public void exec(String sql) throws Exception {
try { this.transactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
this.transactionStatus = hibernateTransactionManager.getTransaction(this.transactionDefinition);
jdbcTemplate.execute(sql);
}
catch (DataAccessException dae) {
log.error(dae);
throw dae;
}
}
public void delete(Entity<T> entity) throws Exception {
dao.getHibernateTemplate().delete(entity);
}
.....
}
I also had to enable FLUSH_EAGER:
Code:
dao.getHibernateTemplate().setFlushMode(HibernateAccessor.FLUSH_EAGER);
i know the design is awfull, but i had to stick to the api of the db class.
as told, everything works now... maybe somebody needs this sometime (but i don't think so...)
Another question that aroused was that the HibernateTransactionManager should be able to rollback the jdbc stuff as well. i got this exception when mixing HibernateTransactionManager and DataSourceTransactionManager:
Code:
org.springframework.transaction.IllegalTransactionStateException:
Pre-bound JDBC Connection found! HibernateTransactionManager does not support
running within DataSourceTransactionManager if told to manage the DataSource
itself. It is recommended to use a single HibernateTransactionManager for all
transactions on a single DataSource, no matter whether Hibernate or
JDBC access.
So i switched completeley to HibernateTransactionManager. But on the JDBC stuff i have to still call conn.rollback(). otherwise it won't roll back.
Has anybody experienced somthing similiar (when combing jdbc and hibernate). Are there any know drawbacks/bugs/caveats. Or is there even a nicer pattern for doing this?
best regards...