こんにちは!今回は、Spring Frameworkでトランザクション管理に使用されるアノテーション、@Transactionalについて詳しく解説します。@Transactionalを使うことで、データベースの操作における整合性を保ち、エラーが発生した際に自動的にロールバックできるようになります。
@Transactionalとは?
@Transactionalとは、
「メソッドやクラスにトランザクションを付与するためのアノテーション」
のことです。
たとえば、複数のデータベース操作を行うときに、途中でエラーが発生した場合、全ての操作をなかったことにしてデータの整合性を保つことができます。これがロールバックです。データベースの一部が更新され、一部が失敗するような事態を防ぐために、トランザクション管理が必要不可欠です。
Spring Frameworkでは、@Transactionalを使用してトランザクションを簡単に制御できます。
たとえば、銀行の振込処理で、送金者の口座からお金を引き落としたものの、受取人の口座に反映されない場合、システムはデータの不整合に陥ります。これを防ぐために、エラーが発生した場合に自動的に処理を元に戻すことが重要です。
基本的な使い方
まずは、簡単なコード例を見てみましょう。複数のデータベース操作を行い、エラーが発生した場合にロールバックするケースを紹介します。
サーバー側のコード
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional // このメソッド全体がトランザクションとして扱われます
public void updateUser(Long id, String newEmail, String newAddress) {
User user = userRepository.findById(id).orElseThrow();
user.setEmail(newEmail);
user.setAddress(newAddress);
userRepository.save(user);
}
}
このコードでは、@Transactionalを付けることで、メソッド内の操作がすべてトランザクションとして実行されます。もしuserRepository.save(user)
の途中で何らかのエラーが発生した場合、それまでの変更はすべてロールバックされ、データベースの状態は更新されません。
トランザクションの基本動作
- 開始: メソッドが呼び出されると同時にトランザクションが開始されます。
- コミット: メソッドが正常に終了すると、すべてのデータベース操作が確定され、変更がデータベースに保存されます。
- ロールバック: メソッドの途中で例外が発生した場合、全ての操作がロールバックされ、データベースに何の影響も残しません。
@Transactionalの引数
@Transactionalには、様々な引数があり、トランザクションの挙動を詳細に制御することができます。ここでは主な引数を解説します。
1. propagation
propagation
は、トランザクションの伝播(トランザクションがどのように他のトランザクションと連動するか)を指定します。
- REQUIRED: 既存のトランザクションがあればそれを使い、なければ新しく作成します(デフォルト)。
- REQUIRES_NEW: 常に新しいトランザクションを開始し、既存のトランザクションは一時停止します。
- NESTED: 既存のトランザクション内でネストされたトランザクションを開始します。
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveNewUser(User user) {
userRepository.save(user);
}
2. isolation
isolation
は、トランザクションの分離レベルを設定します。データベースの競合を防ぐために重要です。
- READ_UNCOMMITTED: 他のトランザクションがコミットされていない変更を読むことができます。
- READ_COMMITTED: 他のトランザクションがコミットした変更のみ読み取ります(デフォルト)。
- REPEATABLE_READ: トランザクション中は同じクエリで常に同じ結果が得られます。
- SERIALIZABLE: 最も厳しい分離レベルで、完全なトランザクションの順次実行を保証します。
@Transactional(isolation = Isolation.SERIALIZABLE)
public void performSensitiveOperation() {
// 厳密な分離レベルでトランザクションを管理
}
3. timeout
timeout
は、トランザクションの実行時間の制限を設定します。指定した時間内にトランザクションが完了しない場合、自動的にロールバックされます。
@Transactional(timeout = 5) // 5秒以内に完了しない場合ロールバック
public void processData() {
// 処理内容
}
4. rollbackFor
rollbackFor
は、特定の例外が発生したときにのみロールバックを行いたい場合に使用します。
@Transactional(rollbackFor = CustomException.class)
public void updateData() throws CustomException {
// カスタム例外が発生した場合のみロールバック
}
5. noRollbackFor
noRollbackFor
は、特定の例外が発生してもロールバックを行いたくない場合に使用します。
@Transactional(noRollbackFor = IllegalArgumentException.class)
public void processRequest() {
// IllegalArgumentExceptionが発生してもロールバックしない
}
まとめ
@Transactionalを使えば、Springアプリケーションにおけるデータベース操作の信頼性を簡単に確保できます。複数の操作をトランザクションとしてまとめ、エラーが発生した場合に自動でロールバックすることで、データの整合性を保つことができます。Springが提供する豊富な設定オプションを活用して、アプリケーションに合ったトランザクション管理を実現しましょう。
もっと詳しく知りたい方は、Spring公式ドキュメントを見てみてくださいね。
他のMappingアノテーションについて知りたい方はこちらもどうぞ!↓↓↓↓