> Markdown version of [Programmatic Transactions](https://vaadin.com/docs/latest/building-apps/forms-data/consistency/transactions/programmatic). Section index: [llms.txt](https://vaadin.com/docs/latest/building-apps/llms.txt)

# Programmatic Transactions

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:

```java
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()`.

```java
@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](https://vaadin.com/docs/latest/building-apps/forms-data/consistency/transactions/declarative.md#caveats) documentation page, there is a similar example that behaves differently.

For more information about programmatic transaction management, see the [Spring Documentation](https://docs.spring.io/spring-framework/reference/data-access/transaction/programmatic.html).

## <a id="committing"></a>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.

## <a id="rolling-back"></a>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:

```java
@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.

## <a id="isolation-level"></a>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 *repeatable read* isolation level:

```java
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_REPEATABLE_READ);
    }
    ...
}
```

For more information about the isolation levels, see the [Transactions](https://vaadin.com/docs/latest/building-apps/forms-data/consistency/transactions.md#transaction-isolation) documentation page.
