6. トランザクション管理
Spring Framework 6章 トランザクション管理
6.1. トランザクション管理の中心となるインタフェース
データベースを扱うアプリケーションではほぼ必ずと言っていいほどトランザクション管理を行う必要があります。しかしながら、JTA, JDO, JDBC,
Hibernate, iBatis 等ではトランザクションを扱う方法は異なります。Spring ではこれらのトランザクションを統一的に扱う方法が用意されており、大きく分けて宣言的トランザクション管理とプログラマティックなトランザクション管理の
2つがあります。宣言的なトランザクション管理とは EJB の CMT (Container Managed Transaction) に良く似たもので、設定ファイルに基づきコンテナがトランザクションを制御します。一方、プログラマティックなトランザクション管理においては、他のトランザクション
API よりもシンプルで簡単な API が提供されます。一部の例外を除き Spring では宣言的なトランザクション管理が推奨されています。宣言モデルを使用するとトランザクション管理に関するコードをほとんど、または全く書く必要がなくなります。このことはコードが
Spring や他のトランザクション API に依存しなくなることを意味します。Spring のトランザクション管理機能を利用することには以下のメリットがあります。
- 異なるトランザクション API をまたぐ一貫したプログラミングモデルが提供される
- Spring のデータアクセス機能との統合
トランザクションを統一的に扱うために Spring では org.springframework.transaction.PlatformTransactionManager
インタフェースを用意しています。このインタフェースは Spring のトランザクション管理における中心的なものです。このインタフェースでは以下のメソッドが定義されています。
TransactionStatus getTransaction(TransactionDefinition definition)
throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
getTransaction() メソッドは実行中のトランザクションまたは新たなトランザクションを返します。getTransaction()
メソッドの動作は引数である org.springframework.transaction.TransactionDefinition
により決定されます。その TransactionDefinition には以下の 4つの設定があります。
- トランザクションの分離レベル
- トランザクションの振る舞い
- トランザクションがタイムアウトする時間
- 読み取り専用かどうか
ここで設定される項目の中でも特に重要なのはトランザクションの分離レベルとトランザクションの振る舞いです。いずれも TransactionDefinition
のフィールドで定義されています。以下はトランザクションの振る舞いに関するフィールドです。同じ値でも既存のトランザクションが存在するかどうかにより振る舞いが異なります。
| フィールド名 |
トランザクション |
| あり |
なし |
PROPAGATION_REQUIRED |
既存のトランザクション内で処理を実行 |
新たなトランザクションを開始 |
PROPAGATION_SUPPORTS |
既存のトランザクション内で処理を実行 |
トランザクション外で処理を実行 |
PROPAGATION_MANDATORY |
既存のトランザクション内で処理を実行 |
例外をスロー |
PROPAGATION_REQUIRES_NEW |
既存のトランザクションを停止し、新たなトランザクションを開始
トランザクションが終了すると停止したトランザクションを再開 |
新たなトランザクションを開始 |
PROPAGATION_NOT_SUPPORTED |
既存のトランザクションを停止し、トランザクション外で処理を実行
処理が終了すると停止したトランザクションを再開 |
トランザクション外で処理を実行 |
PROPAGATION_NEVER |
例外をスロー |
トランザクション外で処理を実行 |
PROPAGATION_NESTED |
既存のトランザクション内で新たなトランザクションを開始 |
新たなトランザクションを開始 |
一方、トランザクションの分離レベルは以下のように定義されており、java.sql.Connection の定数フィールドに対応しています。
| フィールド名 |
対応する java.sql.Connection のフィールド名 |
説明 |
ISOLATION_DEFAULT |
なし |
DBMS のデフォルトの分離レベル |
ISOLATION_READ_UNCOMMITTED |
TRANSACTION_READ_UNCOMMITTED |
ダーティリード、ノンリピータブルリードおよびファントムインサートが起こる |
ISOLATION_READ_COMMITTED |
TRANSACTION_READ_COMMITTED |
ダーティリードは抑制され、ノンリピータブルリードおよびファントムインサートが起こる |
ISOLATION_REPEATABLE_READ |
TRANSACTION_REPEATABLE_READ |
ダーティリードおよびノンリピータブルリードは抑制され、ファントムインサートが起こる |
ISOLATION_SERIALIZABLE |
TRANSACTION_SERIALIZABLE |
ダーティリード、ノンリピータブルリードおよびファントムインサートが抑制される |
commit(), rollback() メソッドは、それぞれ org.springframework.transaction.TransactionStatus
を実装したクラスのプロパティ値に基づいてトランザクションをコミット、ロールバックします。TransactionStatus
には以下のメソッドが定義されています。
boolean isNewTransaction()
void setRollbackOnly()
boolean isRollbackOnly()
boolean 型の値を返す 2つのメソッド isNewTransaction(), isRollbackOnly()
はトランザクションの状態を返すメソッドで、返り値のない setRollbackOnly() はトランザクションを制御するメソッドです。setRollbackOnly()
メソッドを呼び出すとトランザクションはロールバックされます。