手動JPAトランザクションと宣言的@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);
}
}
このコードに問題がありますか? お知らせください。
モダンな方法が優れている理由
ボイラープレートなし
1つのアノテーションが、繰り返されるbegin/commit/rollbackのtry-catchブロックを置き換えます。
安全なロールバック
コンテナが非チェック例外時のロールバックを保証します——catchブロックを忘れるリスクがありません。
宣言的制御
伝播・分離レベル・ロールバックルールをアノテーション属性で表現できます。
旧来のアプローチ
手動トランザクション
モダンなアプローチ
@Transactional
JDKバージョン
11
難易度
中級
JDKサポート
手動JPAトランザクションと宣言的@Transactionalの比較
利用可能
Jakarta EE 8 / Java 11以降、広く利用可能
仕組み
手動のトランザクション管理では、try-catchブロックで囲まれた明示的なbegin()・commit()・rollback()呼び出しが必要で、サービスメソッドごとにこのボイラープレートを繰り返します。@Transactionalアノテーションはライフサイクル管理をコンテナに委ねます。メソッド実行前にトランザクションを開始し、成功時にコミット、RuntimeException発生時に自動でロールバックします。
関連ドキュメント