1 - Logical Transaction vs Physical Transaction

@Service
public class UserService {

    @Autowired
    private InvoiceService invoiceService;

    @Transactional
    public void invoice() {
        invoiceService.createPdf();
        // send invoice as email, etc.
    }
}

@Service
public class InvoiceService {

    @Transactional
    public void createPdf() {
        // ...
    }
}

Now in terms of database transactions, this should really just be one database transaction (i.e. getConnection() → setAutoCommit(false) → commit()). Spring calls this physical transaction

From Spring’s side however, there’s two logical transactions happening: First in UserService, the other one in InvoiceService

2 - Propagation Level

@Transactional(propagation = Propagation.REQUIRED)
@Transactional(propagation = Propagation.SUPPORTS)
@Transactional(propagation = Propagation.MANDATORY)
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Transactional(propagation = Propagation.NOT_SUPPORTED)
@Transactional(propagation = Propagation.NEVER)
@Transactional(propagation = Propagation.NESTED)

REQUIRED (default)

My method needs a transaction, either open one for me or use an existing one

getConnection(). setAutocommit(false). commit()

SUPPORTS

I don’t really care if a transaction is open or not, i can work either way

nothing to do with JDBC

MANDATORY

I’m not going to open up a transaction myself, but I’m going to throw exception if no one else opened one up

nothing to do with JDBC

REQUIRE_NEW

I want my completely own transaction

getConnection(). setAutocommit(false). commit()

NOT_SUPPORTED

I really don’t like transactions, I will even try and suspend a current, running transaction

nothing to do with JDBC

NEVER

I’m going to throw exception if someone else started up a transaction

nothing to do with JDBC

NESTED

It sounds so complicated, but we are just talking savepoints!

connection.setSavepoint()