【Spring Boot】@Transactional の基本をやさしく解説

Java入門・実践
スポンサーリンク
スポンサーリンク

はじめに

Spring Boot でデータを扱うとき、
@Transactional というアノテーションをよく目にします。

  • どこに付ければいいの?
  • 何をしてくれるの?
  • 付け忘れるとどうなるの?

こういった疑問は、実務でも頻出です。

この記事では、@Transactional の基本を
やさしく・実務寄り で整理していきます。

まずはコードから見ていきましょう。


まずはコードを確認

Java
@Service
public class OrderService {

    @Transactional
    public void createOrder(OrderRequest req) {
        // 複数の DB 操作
        orderRepository.save(order);
        stockRepository.decrease(req.getItemId());
    }
}

このように、
複数の DB 操作をまとめて 1 つの処理として扱う
のが @Transactional の役割です。


@Transactional を一言でいうと…

「複数の DB 操作をまとめて、成功なら全部反映・失敗なら全部なかったことにする仕組み」

です。

  • 成功 → commit
  • 失敗 → rollback

この“全部まとめて扱う”のがトランザクションです。


もう少し深く理解する

commit(コミット)

すべての処理が成功したら、DB に反映します。

rollback(ロールバック)

途中で例外が起きたら、 すべての変更を取り消します。

例:

  • 注文は保存された
  • でも在庫更新でエラー
    → 注文も保存されなかったことにする

これがトランザクションの強さです。


@Transactional を付ける場所

基本は Service 層

理由

  • Controller は HTTP の層
  • Repository は DB の層
  • Service が“業務処理のまとまり”を持つ層だから
Java
@Service
@Transactional
public class OrderService { ... }

クラスに付けると、すべての public メソッドが対象になります。


@Transactional のよく使うオプション

readOnly = true

読み取り専用のときに使います。

Java
@Transactional(readOnly = true)
public User findUser(Long id) { ... }

メリット:

  • パフォーマンスが良くなる
  • 不要な更新を防げる

rollbackFor

特定の例外でロールバックしたいとき。

Java
@Transactional(rollbackFor = Exception.class)

デフォルトでは RuntimeException のみロールバック対象です。


実務でよくあるつまずき

private メソッドには効かない

@Transactional は public メソッド にしか適用されません。

同じクラス内のメソッド呼び出しには効かない

自己呼び出し(self-invocation)は AOP が働かないため、
@Transactional が無視されます。

チェック例外ではロールバックされない

デフォルトでは RuntimeException のみロールバック対象です。

Controller に付けるのはアンチパターン

HTTP と DB の境界が曖昧になります。


@Transactional が必要な場面

複数の Repository を操作するとき

Java
orderRepository.save();
stockRepository.update();

更新 → 参照 → 更新 のような複合処理

業務ロジックのまとまりを守るために必要です。

途中で例外が起きたら全部取り消したいとき

データの整合性を守るために必須です。


@Transactional が不要な場面

単純な参照(findById など)

readOnly = true で十分。

単一の save のみ

Repository が内部でトランザクションを扱うため、
必ずしも Service に付ける必要はありません。


あわせて知っておきたいポイント

トランザクションは「境界」を決めるもの

Service 層に付ける理由はここにあります。

Spring のトランザクションは AOP で実現されている

メソッドの前後に処理を挟む仕組みです。

@Transactional はネストできる

ただし挙動は少し複雑なので注意。


まとめ

@Transactional は、
「複数の DB 操作をまとめて 1 つの処理として扱うための仕組み」
です。

  • 成功 → commit
  • 失敗 → rollback
  • 基本は Service 層に付ける
  • readOnly や rollbackFor も便利
  • private メソッドや自己呼び出しには効かない

難しく聞こえますが、
「業務処理のまとまりを守るためのアノテーション」
と理解できれば十分です。

decopon
decopon

@Transactional を理解すると、
データの整合性を守る設計が一気にクリアになります。
“どこに付けるべきか”が分かるだけで、
実務の安定感がぐっと上がります。
あなたの開発が、今日より少しだけ楽になりますように。

moco
moco

全部成功したら OK、失敗したらなかったことに…
やさしい仕組みだね。

コメント

タイトルとURLをコピーしました