Docs

Documentation versions (currently viewingVaadin 24)

Programmatic Transactions

How to manage programmatically transactions in Vaadin applications.

Spring supports managing transactions programmatically through TransactionTemplate and PlatformTransactionManager. The following example demonstrates how to do this. You inject an instance of PlatformTransactionManager into your service, create a new TransactionTemplate, and use it to execute code inside transactions:

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;

@Service
public class MyApplicationService {

    private final TransactionTemplate transactionTemplate;

    MyApplicationService(PlatformTransactionManager transactionManager) {
        transactionTemplate = new TransactionTemplate(transactionManager);
        transactionTemplate.setPropagationBehavior(
            TransactionDefinition.PROPAGATION_REQUIRES_NEW); // (1)
    }

    public void myMethod() {
        transactionTemplate.executeWithoutResult(tx -> { // (2)
            ...
        });
    }

    public String myOtherMethod() {
        return transactionTemplate.execute(tx -> { // (3)
            ...
            return "foo";
        });
    }
}
  1. The propagation behavior is used for all transactions executed using this TransactionTemplate. If you require different propagation behavior, you need different templates.

  2. Use executeWithoutResult for void methods.

  3. Use execute for methods that return a value.

Programmatic transaction management is more verbose than declarative transaction management, but provides better control. Instead of relying on a proxy and a method interceptor, the method controls its own transactions. This removes the limitations of declarative transaction management.

In the following example, myFirstMethod() executes inside its own transaction, regardless of whether it’s called directly by a client, or by mySecondMethod().

@Service
public class MyApplicationService {

    private final TransactionTemplate txRequired;
    private final TransactionTemplate txRequiresNew;

    MyApplicationService(PlatformTransactionManager transactionManager) {
        txRequired = new TransactionTemplate(transactionManager);
        txRequiresNew = new TransactionTemplate(transactionManager);
        txRequiresNew.setPropagationBehavior(
            TransactionDefinition.PROPAGATION_REQUIRES_NEW); // (1)
    }

    public void myFirstMethod() {
        txRequiresNew.executeWithoutResult(tx -> {
            ...
        });
    }

    public void mySecondMethod() {
        txRequired.executeWithoutResult(tx -> {
            ...
            myFirstMethod();
        });
    }
}

On the Declarative Transactions documentation page, there is a similar example that behaves differently.

For more information about programmatic transaction management, see the Spring Documentation.

Committing

You don’t have to do anything special to commit a transaction. Spring commits the transaction after the callback returns, unless it has been marked for rollback.

Rolling Back

You can rollback the transaction in two ways. You can either throw an unchecked exception, or use the setRollbackOnly() method on the TransactionStatus object that is passed to the callback. In the following example, both methods rollback the transaction:

@Service
public class MyApplicationService {
    ...

    public void myMethod() {
        transactionTemplate.executeWithoutResult(tx -> {
            throw new RuntimeException("This causes a rollback");
        });
    }

    public void myOtherMethod() {
        transactionTemplate.executeWithoutResult(tx -> {
            tx.setRollbackOnly(); // This also causes a rollback
        });
    }
}

Unlike declarative transactions, you can’t throw checked exceptions when using programmatic transactions.

Isolation Level

You can set the transaction isolation level on the TransactionTemplate. It uses by default the database implementation’s own default transaction level. The following example configures the TransactionTemplate to use the read uncommitted isolation level:

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;

@Service
public class MyApplicationService {

    private final TransactionTemplate transactionTemplate;

    MyApplicationService(PlatformTransactionManager transactionManager) {
        transactionTemplate = new TransactionTemplate(transactionManager);
        transactionTemplate.setIsolationLevel(
            TransactionDefinition.ISOLATION_READ_UNCOMMITTED);
    }
    ...
}