DI (Dependency Injection)
DI のプログラミング
JavaEE の場合、コンテナがインジェクション先のインタフェースを実装したセッション Bean を自動的に選択し、インジェクションまでしてくれる。この機能をオートワイヤリングという。ただし、当該インタフェースを実装したクラスが複数ある場合は、@EJB アノテーションの beanName 属性でインジェクションするクラスの論理名を指定する。
論理名は、何も指定しない場合にはセッション Bean のパッケージ名を除く名前になるが、@Stateless アノテーションの name 属性で明示的に指定することも可能。
マルチスレッド環境における DI の利用方針
サーブレットクラスのフィールド変数に対してインジェクションをする場合には、インジェクションされるオブジェクトは当然スレッドセーフでなければならない。
一方、セッション Bean のオブジェクトは同時に別のスレッドに割り当てらることはないので、スレッドセーフである必要はない。
セッション Bean の単体テスト
単体テストの場合は、コンテナが実施するインジェクションを自分で実施すればよい。インジェクションするオブジェクトをモックなどにすれば、JavaSE 環境であっても容易に様々なテストが可能となる。
セッション Bean とトランザクション
トランザクションとは
悲観的ロックが排他ロック(SELECT FOR UPDATE) によって他トランザクションによる更新をブロックする方式。楽観的ロックは、更新タイミングで、更新対象が他トランザクションによって書き変えられていないかをチェックする方式。楽観的ロックの方法としては、以下のようなものがある。
- テーブルにバージョン番号を持たせておく方法
- テーブルの最終更新時間を使用する方法
アイソレーションレベル
- ダーティリード
トランザクションが更新した内容が、コミット/ロールバック前に他のトランザクションに見えてしまう現象
- ノンリピータブルリード
一つのトランザクション内で複数回検索を行ったとき、別トランザクションで更新された内容が検索結果を変化させてしまう現象。
- ファントムリード
一つのトランザクション内で複数回検索を行ったとき、別トランザクションで挿入/削除された内容が検索結果を変化させてしまう現象。
複数の ACID トランザクションをまたいだ業務取引をロングトランザクションという。ロングトランザクションの場合は、悲観的ロックだけではデータの整合性が崩れるため、楽観的ロックで整合性を保証する。
Java アプリケーションによるトランザクション管理
トランザクションマネージャを使用しない場合であっても、JDBC の API (Connection インタフェースの commit/rollback) によってトランザクション管理が可能。ただし複数メソッドをまたいで 1 トランザクションを実現するためには、Connection インタフェースを持ち回る必要がある。
一方、JTA トランザクションは Connection インタフェースを持ち回る必要がない。JTA トランザクション境界内で接続プールからコネクションを取得した場合、当該トランザクションと物理コネクションとの関連づけをデータソース側が行うようになる。境界内で論理コネクションを取得した場合は、常におなじ物理コネクションが返却されることが保証される。