次の問題があります。テーブル内のいくつかの要素の順序を保存する必要があります。これは注文番号によって行われます。したがって、最初の要素には注文1があり、10番目には注文10などがあります。また、ブランド値が保存されています。つまり、注文は1つのブランドのすべての行内でのみ行われます。私の構成は、Hibernate4.1.6とSpringDataを備えたSpring3.1です。また、JPAインターフェースを使用し、基盤となるのはMysqlデータベースです。
私は今、namedqueryによって最大値を取得するsaveメソッドを持っています。次に、値を1つインクリメントします。そして、オブジェクトセッターで値を設定します。次にそれを保存します。
if(tag.getOrdering()==0) {
int newOrderingNumber = tagRepository.getMaximumOrderingNumber();
newOrderingNumber++;
if(LOGGER.isDebugEnabled()) {
LOGGER.debug("Next Ordering Number for Tag is " + newOrderingNumber);
}
tag.setOrdering(newOrderingNumber);
}
ここで、2つのスレッドが同時にこれを実行するとどうなるかという問題があります。どちらも同じ値を保存します。ただし、2回インクリメントする必要があります。私の質問は、どうすればこれを防ぐことができるかということです。最初に私は春のトランザクションの分離レベルで何かをしようとしましたが、JPAはトランザクションレベルと、ここのようにjpadialectを拡張する方法を見つけた方法を知っています(http://amitstechblog.wordpress.com/2011/05/31 / support-custom-isolation-levels-with-jpa /)しかし、それは機能しませんでした。接続は常に読み取り専用でした。readOnly= falseフラグが正しく設定されておらず、何が問題なのかわかりませんでした。また、それでは私の問題は解決しないと思います。
次に、@ Versionプロパティを操作しようとしましたが、1つのオブジェクトインスタンスを操作していないため、これは機能しません。2つのスレッドは2つの異なる行で動作しているため、バージョン管理では問題は解決しません。
だから今、私は4つの異なるアプローチを見ています。
最初に:コード内で同期ロックオブジェクトを使用して、一方のスレッドがもう一方のスレッドがオブジェクトのロックを解放するのを待つことができます
2番目:完全なテーブルロックを取得できましたが、休止状態の処理方法がわかりません。また、テーブル全体をブロックするには大きすぎるようです。
3番目:順序が同じである可能性のあるブランド列がない場合は、例外をスローする一意の制約を追加して、機能するまでもう一度インクリメントすることができます。
4番目:今、私はうまくいく可能性のある追加の方法を見つけました。注文番号は保存しません。代わりに、次の要素のIDを順番に含む列を追加します。これは、注文のすべてのリクエストに結合があることを意味しますが、このテーブルには多くの行がないことを知っているので、パフォーマンスは実際には重要ではありません。また、注文が変更されたときの更新もはるかに簡単になります。
では、この問題を解決する正しい方法は何でしょうか。また、順序が変更されたときにすべてのオブジェクトを更新する必要がある場合にも、問題を解決する必要があります。