5

J2EE アプリケーションにキャッシング層を作成しました。この例では、Ehcache を使用します。これにより、いくつかの課題が生じました。

この例を見てみましょう。

OrderItem orderitem = cache.getOrderItemByID("id");
OrderItem old_orderitem = cache.getOrderItemID("id");

orderitem.setStatus(1);
old_orderitem.setStatus(2);

注意しないと、これらのオブジェクトのいずれかに変更を加えると、他のオブジェクトに影響を与えます (同じオブジェクトを参照します)。orderitem をデータベースに保存すると、status=2 になります。

これをどのように解決するのが最善でしょうか?

各オブジェクトに .copyObject() メソッドを作成してみました。新しいオブジェクトを作成し、すべての値を設定するだけです。しかし、これは良い解決策とは思えません。

この例は、単に説明するためのものです。コードはそれよりもはるかに複雑ですが、結果は同じです。

**********************2010年7月15日更新************************ **************************

EHCache 2 には、copyRead() と copyWrite() を有効にするオプションがいくつかあります。そして、これは私の問題をすべて解決します:)

4

4 に答える 4

6

これは可変状態の問題です。キャッシングだけでなく、同じオブジェクトへの複数の参照を持つことができ、そのオブジェクトが可変であるときはいつでもです。例えば:

HashMap map = new HashMap();
map.put("one", new OrderItem());
OrderItem one = map.get("one");
OrderItem two = map.get("one");
one.setStatus(1);
two.setStatus(2);

まったく同じ問題が発生します。並行環境がある場合、これはさらに複雑になります。これを解決する 1 つの方法は、不変オブジェクトのみを使用することです。そうすれば、別の状態のオブジェクトが必要な場合は、新しいオブジェクトを作成する必要があります。また、並行プログラミングも容易になります。

オブジェクトのコピーを検討するのは正しいです。オプションは次のとおりです。

それぞれに長所と短所があり、どれが最適かは環境によって異なります。

于 2010-01-07T17:47:49.963 に答える
1

オブジェクト自体 (たとえば、別の場所で取得したいユーザーのセッション データ) ではなく、オブジェクトを表すデータ (データベース クエリの結果など) をキャッシュしたいようです。

この場合、カスタム キャッシュ レイヤー (ehcache 周辺) は、ユーザーが要求を行うときにキャッシュ データからオブジェクトを作成する必要があります。これにより、毎回一意のオブジェクトが提供され、オブジェクトの干渉が発生しなくなります。

于 2010-01-07T17:31:04.040 に答える
0

Ehcache は、明示的なロック API を介してキーをロックするためのサポートを提供します。読み取りおよび書き込みロックを使用して、キャッシュ内のキーをロックできます。これはキャッシュ内の値をロックしないため、プログラマーがそのように決定した場合、オブジェクトは依然として変更可能です。

これは、あなたがそれをどのように見るかに応じて、言及した問題を解決する場合としない場合があります。プログラマーが規律を守り、取得したオブジェクトを読み取り目的でのみ使用し、取得したオブジェクトをキーの書き込みロックで変更してキャッシュを更新する場合、これは機能するはずです。

ただし、ジェイミー・マクリンドルが言及しているように、可変状態の問題は解消されません。

参照: http://ehcache.org/documentation/explicitlocking.html

于 2011-07-21T09:05:52.150 に答える
0

ID(getOrderItemById)でキャッシュから取得する場合、「 id =で一意に識別されるオブジェクトを取得する」ことを意味すると思います。2 番目の抜粋では、2 つの異なるオブジェクトがある (または取得しようとしている) ため、コードで 2 つの矛盾することを実行しようとしているように見えます。

uniqueness-Id="ID" が常に同じオブジェクトであることを強制できます。ステータスを設定してからリセットすると、同じオブジェクトに新しいステータスがあることを意味します。ID も一致する場合に true を返すように .equals メソッドを拡張することをお勧めします。

「ダーティ」フラグを使用して、(トランザクション?) データ ストアから変更されたオブジェクトをマークすることもできます。

コピーを作成することもこれに対処するための悪い方法ではありませんが、2 つのオブジェクトが同じ ID で実行されていることが何を意味するのかは明確ではありません。キャッシュにまだ存在しないことを示すために、null id を使用してコピーを作成する必要があるのではないでしょうか?

アプリケーションの正しい動作は何ですか?

于 2010-01-07T17:34:55.890 に答える