Enterprise Средний

Ручное управление транзакциями JPA vs. декларативный @Transactional

Замените многословные блоки begin/commit/rollback одной аннотацией @Transactional.

✕ Java EE
@PersistenceContext
EntityManager em;

public void transferFunds(Long from, Long to,
                          BigDecimal amount) {
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    try {
        Account src = em.find(Account.class, from);
        Account dst = em.find(Account.class, to);
        src.debit(amount);
        dst.credit(amount);
        tx.commit();
    } catch (Exception e) {
        tx.rollback();
        throw e;
    }
}
✓ Jakarta EE 8+
@ApplicationScoped
public class AccountService {
    @PersistenceContext
    EntityManager em;

    @Transactional
    public void transferFunds(Long from, Long to,
                              BigDecimal amount) {
        var src = em.find(Account.class, from);
        var dst = em.find(Account.class, to);
        src.debit(amount);
        dst.credit(amount);
    }
}
Заметили проблему в этом коде? Сообщите нам.
🗑️

Никакого шаблонного кода

Одна аннотация заменяет повторяющиеся блоки begin/commit/rollback с try-catch.

🛡️

Более безопасный откат

Контейнер гарантирует откат при непроверяемых исключениях — никакого риска забыть блок catch.

📐

Декларативное управление

Распространение, изоляция и правила отката выражаются как атрибуты аннотации.

Старый подход
Ручная транзакция
Современный подход
@Transactional
Начиная с JDK
11
Сложность
Средний
Ручное управление транзакциями JPA vs. декларативный @Transactional
Доступно

Широко доступно начиная с Jakarta EE 8 / Java 11

Ручное управление транзакциями требует явных вызовов begin(), commit() и rollback(), обёрнутых в блоки try-catch — каждый сервисный метод повторяет этот шаблонный код. Аннотация @Transactional делегирует управление жизненным циклом контейнеру — он запускает транзакцию перед вызовом метода, фиксирует её при успехе и автоматически откатывает при RuntimeException.