2017-08-28 8 views
0

私は、ハイバネートをECacheで設定した広範なデモアプリケーションを使用しています。私はまた、同じdbと直接対話している外部アプリケーションを持っています。 外部アプリケーションを使用してdbを更新すると、それらの変更を認識していない広範なアプリケーションは、新しいエンティティを作成する際に重複した主キーをスローします。私は休止状態を可能にする休止状態のキャッシュを一からクリアすることによってこの問題を解決しようとしています。 次のコードを使用して2番目のレベルのキャッシュをクリアしています。ハイバネートキャッシュをクリアできません

しかし、これは動作していないようです。

私はさらに、visualvmのようなJMXリスナーを使って手動でカフェをクリアしようとしました。しかし、これもうまくいきません。私はまだAPIの古いプライマリキーの値を取得しています。これは、第2レベルのキャッシュだけが第1レベルのキャッシュを残してクリアされているためですか?私はここで立ち往生している。誰でもこの問題を助けてくれますか? UPDATED

はのは、私がアプリケーションBがあるとしましょう。 Aはbroadleafを使用し、Bは生のSQLクエリを使用してdbに挿入します。私はアプリケーションAを使用していくつかの注文を作成し、次にアプリケーションBを使用してデータベースに直接いくつかの注文を挿入します(SEQUENCE_GENERATORテーブルをmax(order_id)+ 1で更新します)。その後、アプリケーションAを使用して注文を作成しようとすると、例外。 IdOverrideTableGeneratorがまだ私の古いプライマリキーを与えていることがわかった問題をデバッグしようとしました。これで2番目のレベルのキャッシュが不思議に思えました。ブロードリーフはプライマリキー生成の参照を開始するためにSEQUENCE_GENERATORを使用せず、キャッシュの現在の状態を維持しますか?私の場合、SEQUENCE_GENERATORを更新しても新鮮でユニークな主キーは保証されません。

+0

max(order_id)アプローチは機能しません。 OrderImplのデフォルトの増分サイズは50です。アプリケーションBからレコードを挿入する前に、事前に(たとえば50件)のIDのバッチを予約する必要があります。これにより、アプリケーションAは、別のバッチを要求した場合にこれらのIDを使用しないことを保証し、アプリケーションBがアプリケーションAを実行しているインスタンスから現在予約されているIDを使用しないことを保証します。アプリBの予約が誤って共有されることはありません。 – mbvcomeback

+1

注文を手動で挿入するためにデータベースに直接アクセスするのではなく、Broadleaf側にAPIエンドポイントを構築して、他のシステムからの注文をBroadleafの「注文」に変換して保存する方がはるかに良いパターンです。次に、2つのシステムをよりよく分離しながら、このsequence_generatorの問題全体を回避することができます。 – phillipuniverse

+0

私はPhillipに同意します。設計要件が許せば、最善の方法は、注文情報を受け入れ、注文を維持するAPIエンドポイントを作成することです。 – mbvcomeback

答えて

2

実行時に新しいエンティティを実装で認識させる場合は、外部インポートに対してL2キャッシュの無効化が必要であるという点では間違いありません。それ以外の場合は、アプリケーションが新しいレコードを表示するために、キャッシュ領域の構成済みTTLが期限切れになるまで待つ必要があります。

しかし、L2キャッシュは、HibernateがBroadleafの場合にプライマリキーをどのように決定するかと直接関係しません。 Broadleafは、パフォーマンスとクラスタに対して安全な方法でIDのバッチを取得するためのテーブルジェネレータ戦略を使用します。スキーマ内にSEQUENCE_GENERATORという名前のテーブルがあることに気が付きました。この表には、異なるドメインクラスに対して取得されたさまざまなID範囲が含まれています。 Hibernateは、挿入のために新しいバッチのIDを取得する必要があるときはいつでも、このテーブルと対話してチェックアウトするための新しいID範囲を登録します。これにより、クラスタ内のどのノードも、衝突するIDを持つエンティティを挿入しようとしません。

あなたのケースでは、外部プロセスが非衝突的に挿入を実行できることを保証する必要があります。これを行うには、外部プロセスが呼び出すためのAPIを作成する必要があると思います。このAPIは、呼び出しプロセスに代わって同じ "IDチェックアウト"操作を実行します。その後、あなたのインポートコード(おそらく他の場所に格納されています)には、安全に使用できるidsの範囲があります。作成したAPIをサポートするコードは、Hibernateがエンティティの挿入用のバッチのIDを取得するために通常実行する操作と同じ操作を実行する必要があります。 org.hibernate.id.enhanced.TableGeneratorを見て、これがどのようなものかの例を見て、自分の目的に似たものを作成することができます。

+0

私は追加したかっただけで、すべてのフレームワーククラスが、休止状態のジェネレータCustomerImplを使用しているわけではありません。それはIdGenerationService – John

+0

良い答えを使用します。鍵は、データベースのレコードを更新するときに、ID範囲を 'SEQUENCE_GENERATOR'で更新する必要があるということです。 @ Johnは、 'BLC_ID_GENERATION'が' CustomerImpl'のためのものであることは間違いありません。 ここに、 'BLC_PRODUCT'のMySQLの例を示します。これは 'ProductImpl'キーがまだない場合にも有効です。 'set @id =(SELECT MAX(product_id)+ 1 FROM blc_product);のセットを直接挿入した後でこれを実行できます。 UPDATE ID_val = @id; ' – phillipuniverse

+0

@phillipuniverseすでにSEQUENCE_GENERATORテーブルの対応するエンティティ値を更新しています。それでもIdOverrideTableGeneratorから古い生成プライマリキーを取得しています。 – amanraj

関連する問題