SpringにはDBのトランザクションの管理を包括的に扱う機能があります。
トランザクションの問題は以外と難しい問題です。
一般的な問題点と、Springでの解決方法を簡単に書いてみます。
【トランザクションの一般的問題点】
1.DBにアクセスするたびに、beginTransaction, commit, rollbackを記述する必要がある。
多人数で開発する場合、記述漏れをする人がいるかもしれない。
2.WEBの場合、リクエストを受け取るController部分(例えばStrutsのAction)の基底クラスで
beginTransaction, commitなどすれば記述漏れの心配が少なくなるが別の問題があります。
ヘルパークラスなどを作成し、static変数にConnectionなどをスレッドローカルで保存しておき、
SQL実行用のstaticメソッドをDAOの中で呼び出す必要がある。
例: TransactionHelper.exceute("select * member");
この問題点は、DAOのソースが絶対にTransactionHelperクラスを使用しなければならなくなり、
他のトランザクション管理に切り替えたい場合に、TransactionHelperクラスを大きく変更する必要が
あることです。
何かフレームワークを使用したくなったときは最悪、上記のメソッド呼び出しの記述をすべて書き換えないと
いけないかもしれません。
つまり、柔軟性が低くなるのです。
3.さらに、上記2の方法は1つのリクエストに対して1回のトランザクションとなっています。
1つのリクエスト内で2回トランザクションを開始するような場合、破綻してしまいます。
他にも細かな問題点はあるかと思います。
プレゼン、ビジネスロジック、DAOと、うまく設計を分けても、トランザクション処理だけは3つの間を横断してしまうことが多いと思います。
真面目な設計者の悩みどころです。
【Springが提供してくれる機能】
(1).宣言的トランザクション
プログラム上からトランザクションの処理の記述を無くせます。
メソッド名を指定すると、指定されたメソッドの開始時に勝手にトランザクション開始し、
メソッド終了時に勝手にコミットしてくれます。
また、例外が発生したときは勝手にロールバックしてくれます。
しかも設定はSpringの設定ファイルに数行記述するだけです
(2).アノテーションによるトランザクション管理
宣言的トランザクションはまとめて一気に設定するイメージです。
つまり、指定したパッケージ、クラス内の同じメソッド名であればすべて同じ設定になります。
それに対してアノテーションを使う方法はメソッドごとにアノテーションを記述するため、
個別にトランザクション管理ができます。
(3).ネストされたメソッドも1つのトランザクションで処理できる (再利用性が高くなる)
例えば、メソッドA()、メソッドB()があったとして、2つともSpringのトランザクションの対象にしたとします。
そして、メソッドA()の中からメソッドB()を呼んだとします。
メソッドB()だけを呼び出した場合、以下のようにトランザクションがかかります。
←トランザクション開始
メソッドB()
←トランザクション終了
メソッドAが呼ばれた場合は、以下のようになります。
←トランザクション開始
メソッドA()開始
メソッドB()の呼び出し
メソッドA()終了
←トランザクション終了
Springトランザクション内部で、すでにトランザクションを開始したかを管理しているために上記のようなことが
できます。
(4).プログラムでのトランザクション管理
上記(1)、(2)のトランザクションの管理の他に、もっと自由にできる方法も用意されています。
上記(1)ではアプリケーション内すべての指定したメソッドに1つのトランザクション管理の方法を提供します。
上記(2)ではクラスもしくは、メソッド1つずつに1つのトランザクション管理の方法を提供します。
プログラムでのトランザクション管理は、プログラムで管理を記述するため、1つのメソッド内でも複数の
トランザクション管理を提供できます。
上記の詳しい内容は、また別の記事で見ていこうと思います。
【問題点との関係】
上記の機能(1)だけで先にあげた問題点が解決しているのが分かるでしょうか?
宣言的トランザクションは、AOP により自動的にトランザクション管理がプログラムに織り込まれます。
織り込みのためのプログラムはSpringが用意しているためプログラム不要です。
そもそもプログラム不要のため、問題点1と2は解決します。
問題点3の複数回のトランザクションをしたい場合。
ビジネスロジックのメソッドは通常、1つの機能ブロック単位で設計されるため、それより細かなトランザクション管理は発生しないはずです。
つまり、通常であれば複数回のトランザクションを行いたい場合は、ビジネスロジックの呼び出し単位のはずです。
宣言的トランザクションは、通常、ビジネスロジックのメソッド毎にかけます。
(指定すればどこにでもかけられますが)
そうすれば、ビジネスロジックが呼び出されるたびに勝手にトランザクションが開始・終了するため、問題点3も勝手に行われます。
また、機能の(4)を使用すれば自由にトランザクション管理できるため、最悪の場合の逃げ道にできます。
とても勉強して使ってみる価値のある機能だと思いませんか?
【まとめ】
プログラム上からトランザクションのコードを無くせるのはすごくないですか
他の記事で見ていきますが、機能もかなり単純化されているので分かりやすいです。
しかも、上記の機能は同時に使っても、上記(3)の機能は生きています。
ふつう、トランザクションの開始・終了処理をメソッド内に書いてしまい、そのメソッドの呼び出し元でもトランザクションの開始・終了を書いてしまうと、rollbackがうまく働かなくなります。
そうなると、あるメソッドはここでは使用できるけど、ここでは使用できない、などの制限ができ、使用時にいろいろ関係性を考えてコードを書かないといけません。
それを気にせずにコードを書けるのは大きなメリットです。
メソッドの再利用性が高くなってますよね!
ぜひ、うまく使って再利用性の高さと、効率化を量りましょう!
参考:
・トップ
・Springのトランザクション機能について・トランザクションのコードを書かないようにするには?(宣言的トランザクション) (←設定値の説明あり)
・アノテーションによるトランザクション管理
・プログラムによるトランザクション管理(TransactionTemplate)