Friday, September 23, 2011

Spring @Transactional Propagation Reference

Spring's propagation types for the @Transactional annotation differ in how they behave in presence/absence of an existing transaction:

Propagation types and their behaviour
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.