MicronautのトランザクションAOPとは?@Transactionalの基本
生徒
「Micronautでデータベース操作を安全に行いたいです。途中で失敗したら元に戻したいんですが、どうすればいいですか?」
先生
「その場合、トランザクションAOPを使うと簡単です。Micronautでは@Transactionalアノテーションを付けるだけで、メソッドの実行中に例外が発生した場合、自動でロールバックされます。」
生徒
「AOPって、以前教えてもらったメソッドの前後に処理を挟む仕組みですよね?」
先生
「そうです。@TransactionalもAOPを使って、メソッド開始時にトランザクションを開始し、終了時にコミットやロールバックを自動で行います。」
1. トランザクションAOPの基本概念
トランザクションAOPとは、データベース操作を行うメソッドの前後でトランザクション処理を自動で挿入する仕組みです。これにより、複数の操作をまとめて一つの単位として処理できます。途中でエラーが発生した場合、変更内容を元に戻すロールバックが行われ、データの整合性を保つことが可能です。
2. @Transactionalアノテーションの使い方
Micronautでは、メソッドやクラスに@Transactionalを付けるだけで、その範囲の処理がトランザクション管理下に置かれます。アノテーションはimport io.micronaut.transaction.annotation.Transactional;で利用できます。
import io.micronaut.transaction.annotation.Transactional;
import jakarta.inject.Singleton;
@Singleton
public class UserService {
@Transactional
public void createUser(String name) {
// データベースにユーザーを登録
}
}
3. メソッド単位とクラス単位の違い
@Transactionalはメソッド単位でもクラス単位でも付与できます。クラスに付与すると、そのクラス内のすべてのメソッドがトランザクション管理対象になります。
@Transactional
@Singleton
public class OrderService {
public void createOrder() {
// 注文作成処理
}
public void cancelOrder() {
// 注文キャンセル処理
}
}
4. ロールバックの仕組み
メソッド実行中に例外が発生すると、@Transactionalによって自動的にロールバックされます。これにより、部分的な変更でデータベースが不整合になることを防ぎます。
@Transactional
public void updateInventory(int productId, int quantity) {
// 在庫更新
if(quantity < 0) {
throw new RuntimeException("在庫不足");
}
}
5. 伝播属性と隔離レベル
@Transactionalは伝播属性や隔離レベルも設定可能です。伝播属性により、既存のトランザクションを再利用するか、新規に開始するかを指定できます。隔離レベルにより、他のトランザクションからのデータ参照を制御できます。
@Transactional(rollbackFor = Exception.class)
public void transferMoney(int fromId, int toId, double amount) {
// 口座振替処理
}
6. AOPによるトランザクションの仕組み
MicronautはAOPを使って@Transactionalを処理します。メソッド呼び出し時にトランザクションを開始し、正常終了でコミット、例外発生でロールバックを実行します。開発者は明示的にトランザクション処理を書く必要がなくなります。
7. 実務での利用ポイント
トランザクション管理は便利ですが、全てのメソッドに付与するとパフォーマンスに影響します。データ整合性が必要な操作だけに限定するのが望ましいです。また、読み取り専用処理にはreadOnly=trueを指定して最適化できます。
@Transactional(readOnly = true)
public List<User> listUsers() {
// ユーザー一覧取得
return userRepository.findAll();
}
8. エラー処理とトランザクション管理
例外処理はロールバックに影響します。チェック例外ではロールバックされない場合があるため、rollbackFor属性で指定することが重要です。これにより意図しないデータのコミットを防ぎます。