I have a JavaEE application using Hibernate to connect to the database. In some part of my application I have calls to method which have a @Transactional
annotation. In some of these cases, I want to rollback the whole transaction (the outer-service-method call, and the inner). And on some occasions I want to rollback only the inner service-method call (that is, rollback to savepoint defined at the start of the internal method).
The first part is already in place, but I have a problem with the second one. When I do the following, I get a "UnexpectedRollbackException" with the message "Transaction rolled back because it has been marked as rollback-only".
@Service
public class OuterService{
@AutoWired
private InnerServcie innerService;
@Transactional
public void outer(){
try{
innerService.inner();
}catch(RuntimeException e){
//if i dont throw this up, it will give me the "UnexpectedRollbackException"
System.out.println("I cought a RuntimeException");
}
}
}
@Service
public class InnerServcie{
@Transactional
public void inner(){
//here we insert some data into db using hibernate
//but something goes wrong and an exception is thrown
}
}
The feature you are looking for is called savepoints. They are not, strictly saying, nested transactions, but milestones in the consequent SQL instruction chain, to which you can rollback. Rolling back to savepoint means invalidating ALL instructions issued from the moment of creating the savepoint, so you can have multiple savepoints, but you can only rollback instructions between now and savepoint, not between 2 savepoints!
Spring supports savepoints, both when using JdbcTransactionObjectSupport manually, and using @Transactional
annotation.
According to the document http://docs.spring.io/spring/docs/2.5.3/reference/transaction.html point 9.5.7.3 you should use Propagation.NESTED
.
However, that options may not be available in your case. From Javadoc:
Note: Actual creation of a nested transaction will only work on specific transaction managers. Out of the box, this only applies to the JDBC DataSourceTransactionManager when working on a JDBC 3.0 driver. Some JTA providers might support nested transactions as well.
As last resort, you can issue SQL instructions starting/rollbacking to savepoint directly.
For PostgreSQL it would be:
SAVEPOINT foo;
ROLLBACK TO SAVEPOINT foo;
Source: http://www.postgresql.org/docs/8.2/static/sql-rollback-to.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With