データベースの更新と同期
|
|
 |
EJB 3.0コンテナはエンティティBeanオブジェクトを直接操作することでデータベース内のデータ行を更新可能にします。その変更は自動的にキューに蓄積され(queued)、データベースに送出されます。このトレイルでは、まさしくデータベースが更新が機能する様子を学びます。
|
|
|
 |
データベース更新を説明するため、投資計算機にTimedRecord テーブル内のすべてのドルの値を別の通貨(currency)へ更新する新機能を実装します。やらなければならないことは、次のフォームの為替変換レートを入力して「更新」ボタンをクリックするだけです。
|
|
|
 |
テーブルの複数行を更新するには、最初にEntityManager APIによってそれらの行をエンティティBeanへ取得すべきです。そうすれば、(データベース内のテーブルカラムにマップされる)任意のデータ属性の更新をするのに、通常のセッターメソッドを使うだけで可能になります。
@Stateless
public class UpdateCalculator implements Calculator {
@PersistenceContext
protected EntityManager em;
// ... ...
public void updateExchangeRate (double newrate) {
Collection <TimedRecord> rc =
em.createQuery("from TimedRecord r").getResultList();
for (Iterator iter = rc.iterator(); iter.hasNext();) {
TimedRecord r = (TimedRecord) iter.next();
r.setSaving(r.getSaving() * newrate);
r.setResult(r.getResult() * newrate);
}
}
}
|
|
|
 |
updateExchangeRate() メソッドでは、すべての計算記録Beanインスタンスを更新するためにループを使っていました。しかし、ループ内で各Beanを更新するためにコンテナがデータベースに対してリモートのSQL更新を送信するというのは遅くて効率が悪いことです。何回もデータベースにアクセスすることは、ネットワークエラーの機会を増大させ、データベースの負荷を増大させます。より良い方法は、キューに更新を蓄積し、ループが終了した後でバッチによってそれらの要求をデータベースと同期させるという方法です。これはコンテナがこのケースでまさに実行していたことです。
デフォルトでは、すべてのEntityManager 操作(新規Beanの永続化、Beanの削除、Beanの更新)は、メモリ上にキャッシュされます。それらは現在スレッド(つまり、メソッド呼び出しスタック)が完了したとき、あるいは次のデータベース問合せが発行される前、のいずれか早い方で、単一のバッチによってデータベースとの同期が行われます。例では、コンテナはupdateExchangeRate() メソッドが完了した直後にすべてのBeanオブジェクトはデータベースと同期させられます。
しかし、ユーザによっては、スレッド内でのデータベース同期のタイミングを手動で正確に制御し、最適化したいと望むかもしれません。例えば、クラスタ内でメモリを削減し、大きなキャッシュ複製を避けるため、早期に変更を送信したいと望むかもしれません。トランザクション内では、EntityManager.flush() メソッドを呼び出すことによって、EntityManager 内の現在のイン・メモリ(in-memory)変更をデータベースに対してフラッシュすることが可能です。EntityManager のフラッシュは、メソッドの途中やコールスタックの途中でのメソッドの最後(つまり、スレッドの途中)で可能です。
|
|
|
 |
ローカルEntityManager は取得済みのエンティティBeanの記録を取り、データベースへの同期が必要となるようなBeanオブジェクトへのすべての更新情報を捕捉します。しかし、ローカルEntityManager から得ることができないエンティティBeanインスタンスについてはどうすればよいのでしょうか。例えば、TimedRecord Beanがネットワーク接続を介してシリアライズされていたとしたらどうしますか。どうやってそれを更新したり、データベースへ同期すべき変更を取得したりできるのでしょう。それをするには、EntityManager.merge() メソッドを使って、その呼び出しパラメタとしてBeanインスタンスを渡すことができるのです。
一般的には、ローカルスレッド以外から得たエンティティBeanを更新するなら、EntityManager.merge() を呼び出してその値をデータベースへ書き戻してマージする必要があります。
|
|
|
 |
セッションBean
JSPユーザインタフェース
|
|
|
 |
このトレイルでは、データベースの更新方法を学習しました。データベース同期戦略と更新されていないエンティティBeanインスタンスのマージについても議論しました。つまり、EJB 3.0では、データベース同期はコンテナのトランザクションマネージャによって管理されるのです。後で登場するトランザクションのトレイルでは、トランザクションマネージャがどのように動作するかについて学びます。次のトレイルでは、エンティティBeanのライフサイクルコールバックについて手短に学びましょう
|
|