我们有一个表,其中每个更新值都有新行。主键由 ID 和时间戳组成。还有一个状态栏。对于特定的 ID,我们将有一行表示每次更新该值,我们使用具有最新时间戳的行来表示“当前”值。
我们有一个基于用户输入更新状态的过程。因此,当用户单击 UI 中的按钮时,将使用新状态和新用户 ID 创建一个新行。
如果两个用户同时单击该按钮,我们只是插入了两条新记录,其中一个将获胜(具有最新时间戳的那个)。我们希望避免让两个用户同时单击此按钮,而一个用户可能会在不知道他们踩到其他人的状态更改的情况下创建一个新行。在 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 吗?