Reputation: 346
What is the difference between method with
@Transactional(propagation = Propagation.SUPPORTS)
and a method without @Transactional
?
For example:
public class TEst {
@Transactional
public void methodWithTransaction1(){
methodWithSupportsTransaction();
}
@Transactional
public void methodWithTransaction2(){
methodWithoutTransactional();
}
@Transactional(propagation = Propagation.SUPPORTS)
public void methodWithSupportsTransaction(){
}
public void methodWithoutTransactional(){
}
}
Upvotes: 2
Views: 719
Reputation: 67
Spring supports two types of transaction management programmatic and declarative.
Programmatic transaction management: In this manner transactions need to be handled by us. For example-
EntityTransaction tran = entityManager.getTransaction();
try {
tran.begin();
methodWithoutTransactional();
tran.commit();
} catch(Exception ex) {
tran.rollback();
throw ex;
}
Declarative transaction management: In this manner, we can separate out transaction management code from our business logic, simply by using annotation or xml based configuration. Which you've already done in example code-
@Transactional
public void methodWithTransaction1(){
methodWithSupportsTransaction();
}
For @Transactional annotation if we do not define the propagation type, PROPAGATION_REQUIRED will be applied by default. You can find the documentation here.
Upvotes: 0
Reputation: 692073
Except for the slight difference indicated in the javadoc regarding synchronization, a difference between both is that a transactional proxy intercepts the method call if the method is annotated with Transactional, and will mark the current transaction, if any, as rollbackOnly if a runtime exception is thrown from that method.
So, let's take an example:
public class A {
@Autowired B b;
@Transactional
public void foo() {
try {
b.bar();
}
catch (RuntimeException e) {
// ignore
}
...
}
}
public class B {
// @Transactional(propagation = Propagation.SUPPORTS)
public void bar() {
throw new RuntimeException();
}
}
Calling a.foo()
will start a transaction if none exists yet (propagation REQUIRED). Then b.bar() will be called and will throw an exception. The exception is caught by a.foo()
, which continues executing as if nothing happened. At the end of a.foo()
, the transaction will be committed successfully.
Now let's uncomment the Transactional annotation on b.bar()
. Calling a.foo()
will start a transaction if none exists yet (propagation REQUIRED). Then b.bar() will be called and will throw an exception. This exception will be "intercepted" by the transactional proxy around B, which will mark the transaction to rollbackOnly. Then the exception will propagate to A. a.foo()
. The exception is caught by a.foo()
, which continues executing as if nothing happened. At the end of a.foo()
, the transaction will be committed, but that commit will fail because the transaction has already been marked as rollbackOnly. The caller of a.foo() will get a TransactionSystemException.
Upvotes: 4