4.4.5.1. Programmatic Transaction Management

Programmatic transaction management is done using com.haulmont.cuba.core.Transaction interface, a reference to which may be obtained via the createTransaction() or getTransaction() methods of the Persistence infrastructure interface.

The createTransaction() method creates a new transaction and returns the Transaction interface. Subsequent calls of commit(), commitRetaining(), end() methods of this interface control the created transaction. If at the moment of creation there was another transaction, it will be paused and resumed after the completion of the newly created one.

The getTransaction() method either creates a new transaction or attaches to an existing one. If at the moment of the call there is an active transaction, then the method completes successfully, but subsequent calls of commit(), commitRetaining(), end() have no influence on the existing transaction. However calling end() without a prior call to commit() will mark current transaction as RollbackOnly.

An example of programmatic transaction management:

@Inject
private Persistence persistence;
...
Transaction tx = persistence.createTransaction();
try {
    EntityManager em = persistence.getEntityManager();
    Customer customer = new Customer();
    customer.setName("John Smith");
    em.persist(customer);

    tx.commit();
} finally {
    tx.end();
}

Transaction interface also has the execute() method accepting an action class as input. This class defines an action which should be performed in this transaction. This allows organizing transaction management in functional style, for example:

persistence.createTransaction().execute(new Transaction.Runnable() {
    public void run(EntityManager em) {
        // transactional code here
    }
});

If the transactional block is expected to return a result, the action class should implement Transaction.Callable interface. If the result is not required as in the example above, it is recommended to inherit the action class from the abstract class Transaction.Runnable.

Keep in mind that execute() method of a given instance of Transaction may be called only once because the transaction ends after the action class code is executed.