4.4.5.1. Программное управление транзакциями

Программное управление транзакциями осуществляется с помощью интерфейса com.haulmont.cuba.core.Transaction, ссылку на который можно получить методами createTransaction() или getTransaction() интерфейса инфраструктуры Persistence .

Метод createTransaction() создает новую транзакцию и возвращает интерфейс Transaction. Последующие вызовы методов commit(), commitRetaining(), end() этого интерфейса управляют созданной транзакцией. Если в момент создания существовала другая транзакция, то она будет приостановлена, и возобновлена после завершения созданной.

Метод getTransaction() вызывает либо создание новой, либо присоединение к текущей транзакции. Если в момент вызова существовала активная транзакция, то метод успешно завершается, и последующие вызовы commit(), commitRetaining(), end() не оказывают никакого влияния на существующую транзакцию. Однако если end() вызван без предварительного вызова commit(), то текущая транзакция помечается как RollbackOnly.

Пример ручного управления транзакцией:

@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 имеет также метод execute(), принимающий на вход класс-действие, которое нужно выполнить в данной транзакции. Это позволяет организовать управление транзакциями в функциональном стиле, например:

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

Если транзакционный блок должен вернуть результат, класс-действие должен реализовывать интерфейс Transaction.Callable. Если результат не требуется, как в приведенном примере, то класс-действие удобно наследовать от абстрактного класса Transaction.Runnable.

Следует иметь в виду, что метод execute() у некоторого экземпляра Transaction можно вызвать только один раз, так как после выполнения кода класса-действия транзакция завершается.