Spring's propagation types for the @Transactional
annotation differ in how they behave in presence/absence of an existing transaction:
PROPAGATION TYPE | no current transaction | there's a current transaction |
---|---|---|
MANDATORY |
throw exception | use current transaction |
NEVER |
don't create a transaction, run method outside any transaction | throw exception |
NOT_SUPPORTED |
don't create a transaction, run method outside any transaction | suspend current transaction, run method outside any transaction |
SUPPORTS |
don't create a transaction, run method outside any transaction | use current transaction |
REQUIRED (default) |
create a new transaction | use current transaction |
REQUIRES_NEW |
create a new transaction | suspend current transaction, create a new independent transaction |
NESTED |
create a new transaction | create a new nested transaction |
It could be argued that NEVER
and NOT_SUPPORTED
(and arguably SUPPORTS
also) don't serve any useful purpose, and exist only for completeness; after all, why would you want to explicitly run something outside of any transaction?
As for the other propagation types, REQUIRED
/MANDATORY
/SUPPORTS
would be used when you want your code to be part of the current transaction, sharing its commit/rollback fate; NESTED
would come into use in cases where you want to be able to rollback only parts of a bigger transaction; and finally REQUIRES_NEW
is to be used when you want to do something totally unrelated to the current transaction.
The difference between REQUIRED
, MANDATORY
and SUPPORTS
strives in how they behave when there is no existing transaction. MANDATORY
acts as a sort of assert
directive, ensuring there is an opened transaction. REQUIRED
creates a new transaction, being safe to use outside any transaction. SUPPORTS
rides along an existing transaction, but doesn't create a new one if none exists.