Reputation: 193
I have code like so
@Transactional(propagation = Propagation.NESTED)
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public class C1 {
...
public void xxx() {
try {
obj.someMethod();
} catch (Exception e) {
C2.yyy();
}
}
}
public class C2 {
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false)
public void yyy() {
...
}
}
My assumption is that when obj.someMethod();
throws a constraint violation exception C2.yyy()
should still be able to save stuff to the DB.
However what I see is that when C2.yyy()
is called Postgres reports
ERROR: current transaction is aborted, commands ignored until end of transaction block
Why should it do that? After all C2.yyy()
should run in a different transaction that should be unaffected by the state of what happened in the invoking code. No?
On further debugging here is what I found - let us say the call stack is like so
@Transactional(readOnly = false, propagation = Propagation.NESTED)
b1.m1()
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
b2.m2()
b3.m3()
b4.m4()
My assumption was that the DB code in m4() would execute in a new transaction because of the annotation on b2.m2(). But it seems the code in TransactionAspectSupport.java looks at the transaction annotation only on the current method and not on the stack. When it does not find any @transactional on m4() it assumes REQUIRES. Isn't this incorrect?
Upvotes: 2
Views: 2289
Reputation: 2888
As answered here DatabaseError: current transaction is aborted, commands ignored until end of transaction block : "This is what postgres does when a query produces an error and you try to run another query without first rolling back the transaction".
Meaning that you 'obj' should run in its own transaction and roll back on exception.
Regarding the question in the update: REQUIRES_NEW always creates a new transaction, it is both documented and tested.
Upvotes: 1