更新された値ごとに新しい行を持つテーブルがあります。主キーは、ID とタイムスタンプで構成されます。ステータス欄もあります。特定の ID について、その値が更新されるたびに表す行があり、最新のタイムスタンプを持つ行を使用して「現在の」値を表します。
ユーザー入力に基づいて状態を更新するプロセスがあります。したがって、ユーザーが UI のボタンをクリックすると、新しい状態と新しいユーザー ID で新しい行が作成されます。
2 人のユーザーが同時にボタンをクリックすると、2 つの新しいレコードが挿入され、そのうちの 1 つ (タイムスタンプが最新のもの) が優先されます。2 人のユーザーが同時にこのボタンをクリックし、1 人のユーザーが他のユーザーの状態変更を踏んだことを知らずに新しい行を作成する可能性を回避したいと考えています。Oracle では、次のようなことを行い、行が挿入されたことを確認します (PREVIOUS_KNOWN_MAX_TS は、ユーザーがページを表示したときの「現在の」レコードの TS です)。
INSERT INTO SOME_TABLE
(ID, REVISION_TS, USER_ID, STATUS, ...)
SELECT 1, 'SOME_TIMESTAMP', 'user123', 'NEW_STATUS', ...
FROM DUAL
WHERE NOT EXISTS
(SELECT *
FROM SOME_TABLE
WHERE USER_ID = 1
AND REVISION_TS >= 'PREVIOUS_KNOWN_MAX_TS'));
ユーザーがページを表示してからユーザーの更新情報が挿入されるまでの間に挿入があった場合、挿入は行われず、ゼロ行が挿入されたことを知ることでそれを検出します。
Hibernate でこれを行う方法はありますか、それとも何らかの SELECT FOR UPDATE を試してみるべきでしょうか?