ホーム画面からユーザー一覧画面に遷移し、ユーザーの詳細を表示するアプリケーションを作成して、Spring JDBCの使い方について学びます⭐️
前回、前々回では宣言的/明示的トランザクションを学びました。
今回は宣言的トランザクション(@Transaction)の設定についてのまとめです^^
構成は前回/前々回の記事を参考にしてください
⭐️前回/前々回の記事
Java・SpringBoot】宣言的トランザクション処理(SpringBootアプリケーション実践編20)
【Java・SpringBoot】明示的トランザクション処理(SpringBootアプリケーション実践編21)
#@Transactionアノテーションの設定
属性 | 説明 |
---|---|
value | 複数のトランザクションマネージャーを使用する場合、利用するトランザクションマネージャーのQualifierを指定する。 デフォルトでは省略可能(transactionManagerも同じ) |
propagation | トランザクションの伝播レベルを指定 |
isolation | トランザクションの分離レベルを指定 |
timeout | トランザクションのタイムアウト時間(秒)を指定。 デフォルトは-1(使用するデータベースの仕様や設定に依存) |
readOnly | トランザクションの読取専用フラグを指定。 デフォルトはfalse(読取専用ではない) |
rollbackFor | トランザクションのロールバック対象とする例外クラスのリストを指定。 デフォルトはRuntimeException(非検査例外)がロールバック対象。 |
rollbackForClassName | トランザクションのロールバック対象とする例外クラス名のリストを指定。 デフォルトは空(指定なし) |
noRollbackFor | トランザクションのコミット対象とする例外クラスのリストを指定。 デフォルトは空(指定なし) |
noRollbackForClassName | トランザクションのコミット対象とする例外クラス名のリストを指定。 デフォルトは空(指定なし) |
#トランザクションの独立性(分離性)
- トランザクションを複数同時に実行しても、正常な処理をしなければならないこと
- 複数ユーザーがアプリケーションを使う場合、トランザクションは複数存在する
- →同じデータを参照する際には注意が必要!
- ex: トランザクションA、Bが同時に口座の情報を読み取り、同時に更新した場合に、データ不整合になってしまう
- トランザクションAが終了するまで、トランザクションBは待機しないといけない
- Springの分離レベルで独立性のレベルを指定
#トランザクション分離レベル
- トランザクションの分離レベルは、isolation属性に以下の値を指定
分離レベル | 説明 |
---|---|
DEFAULT | 利用するデータベースのデフォルトの分離レベルを利用 |
READ_UNCOMMITTED | 他のトランザクションが、まだコミットしていないデータを読み出せる。 変更データがロールバックされた場合、次のトランザクションでは無効な行データが検索される |
READ_COMMITTED | 他のトランザクションがコミットしていないデータは読み出せない |
REPEATABLE_READ | トランザクション内で、複数回データを読み込んだ場合、他のトランザクションが途中でデータを変更しても、同じ値が読み込まれる |
SERIALIZABLE | トランザクションを順番に処理 |
#独立性における代表的な問題
-
ダーティリード
- 他のトランザクションが変更したが、まだコミットしていないデータを読み取ってしまい、誤ったデータを読み取ってしまう
-
ノンリピータブルリード
- トランザクションの中で、何回も同じデータを読み取るときに、他のトランザクションがデータを更新してしまうと、途中から違う値を読み取ってしまう
-
ファントムリード
- トランザクションの中で、何回も同じデータを読み取ると、他のトランザクションが新しくデータを追加すると途中から処理対象のレコードが増える
###分離レベルが問題を解決できるかどうか
分離レベル | ダーティリード | ノンリピータブルリード | ファントムリード |
---|---|---|---|
READ_UNCOMMITTED | × | × | × |
READ_COMMITTED | 〇 | × | × |
REPEATABLE_READ | 〇 | 〇 | × |
SERIALIZABLE | 〇 | 〇 | 〇 |
#トランザクションの伝播レベル
- トランザクションを新たに作成し、開始するかどうかの設定
- 特に、サービスクラスから別のサービスクラスを呼び出す場合、トランザクションを開始するのか、既存トランザクションに参加するのかを設定することができる
- トランザクションを直接呼ぶときは、トランザクション開始する・例外を投げる・作成しないのどれに当てはまるか、
- 間接的に呼ぶときは、参加する・開始する・例外を投げる・作成しない、のどれに当てはまるか、を検討する
伝播レベル | 説明 |
---|---|
REQUIRED | デフォルト設定。トランザクションが存在しない場合、新規にトランザクションを開始。すでに存在する場合はそのトランザクションを利用 |
QUIRES_NEW | 必ず新規のトランザクションを作成 |
MANDATORY | すでにトランザクションが存在することを前提にし、トランザクションが存在しない場合、例外発生。 すでに存在する場合は、そのトランザクションを利用 |
NEVER | トランザクションを使用しない。 すでにトランザクションが存在する場合は例外が発生 |
NOT_SUPPORTED |
トランザクションを使用しない。 すでにトランザクションが存在する場合はそのトランザクションを一時停止し、トランザクションを使用せずに処理を実行後、停止していたトランザクションを再開 |
SUPPORTS | トランザクションが存在しない場合、トランザクション作成しない。 既に存在する場合は、そのトランザクションを利用 |
NESTED |
ネストしたトランザクションを作成。 トランザクションが存在しない場合、新規にトランザクションを開始し、すでに存在する場合はそのトランザクションを利用するが、その部分だけネストしたトランザクションのように処理 |