|
From: <jue...@we...> - 2004-06-19 10:02:06
|
Thomas, Alef, Colin, everybody,
=20
Motivated by Rod, I've added support for nested transactions to our =
transaction infrastructure, via the new propagation behavior =
PROPAGATION_NESTED. The transaction manager needs to open a true nested =
transaction which can be rolled back individually while still being able =
to continue with the surrounding transaction.
=20
Furthermore, application code can also use custom savepoints: The =
TransactionStatus interface now has a SavepointManager superinterface, =
which provides generic means to create savepoints and roll back to them. =
This is only intended for advanced needs where the declarative nested =
transaction model is not sufficient.
=20
DataSourceTransactionManager implements nested transaction support via =
JDBC 3.0 Savepoints: basically, create a Savepoint on nested transaction =
begin, release it on nested transaction commit, roll back to it on =
nested transaction rollback. Of course, DataSourceTransactionManager is =
still compatible with JDBC 2.0 if not using nested transactions.
=20
HibernateTransactionManager and JdoTransactionManager offer support for =
JDBC 3.0 Savepoints too, but it's deactivated by default there: =
Savepoints are just able to roll back the underlying JDBC Connection, =
not the Session respectively PersistenceManager with its object cache. =
Savepoints are still useful for JDBC access code that participates in a =
Hibernate/JDO transaction, though, when used with care.
=20
All of this is already fully covered by unit tests. Unfortunately, I =
don't have a database with savepoint support available here, i.e. no =
Oracle; so I've just been able to test that it fails nicely against =
MySQL (on JDK 1.4 and 1.3). Thomas, do you have a chance to test this =
against a live database?
=20
An example for how PROPAGATION_NESTED is supposed to work. Note that the =
nested transaction sets the rollback-only flag: This should just cause a =
rollback of the second update statement but still allow the surrounding =
transaction to commit the first update statement.
=20
DataSource ds =3D ...;
final PlatformTransactionManager tm =3D new =
DataSourceTransactionManager(ds);
final JdbcTemplate jt =3D new JdbcTemplate(ds);
TransactionTemplate tt1 =3D new TransactionTemplate(tm);
=
tt1.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
tt1.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus =
status) {
jt.update("first update statement");
TransactionTemplate tt1 =3D new TransactionTemplate(tm);
=
tt1.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
tt1.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus =
status) {
jt.update("second update statement");
status.setRollbackOnly();
}
});
}
});
An example for the same effect via manual savepoint management:
=20
TransactionTemplate tt1 =3D new TransactionTemplate(tm);
=
tt1.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
tt1.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus =
status) {
jt.update("first update statement");
Object savepoint =3D status.createSavepoint();
jt.update("second update statement");
status.rollbackToSavepoint(savepoint);
}
});
=20
Juergen
=20
|