Hibernate如何在提交事务前做乐观锁的行版本检查

How does Hibernate do row version check for Optimistic Locking before committing the transaction

在提交当前事务之前,hibernate 检查行的版本,它应该发出一个 sql select 语句来获取 ithe 行。

假设在发出 select 语句后,hibernate 发现行版本没有改变,因此它应该继续提交事务。

我想知道 hibernate 如何确保在选择行和提交当前事务之间的时间段内没有任何其他事务会更新行以更改其版本号? hibernate 唯一可能做的事情似乎是使用 Select ... For Update 进行悲观锁定的行版本选择或具有这种隔离级别的事务将锁定正在读取的行。

如果我想的是真的:

请分享您的想法。

对于默认的乐观锁定机制,即@Version注解给出的机制,没有这种风险。

乐观锁定不需要任何额外的SELECT来获取和检查实体被修改后的版本。因此,涉及两个步骤:

  1. 从数据库中获取实体及其版本:

     SELECT * FROM PRODUCT WHERE ID = 1;
    
  2. UPDATE 或 DELETE 将使用与获取实体相同的 SELECT 获取的版本:

     UPDATE PRODUCT SET (LIKES, QUANTITY, VERSION) = (5, 10, 3) 
     WHERE ID = 1 AND VERSION = 2;
    

因此,Hibernate 不检查实体版本。数据库使用 WHERE 子句对其进行检查。

Hibernate 只检查 PreparedStatement.executeUpdate 方法调用的 updateCount 结果。如果计数不是 updateCount,则意味着该行已被删除或版本已更改,这意味着我们使用的是陈旧数据,因此将抛出 OptimisticLockException

因此,对于默认的基于 @Version 的乐观锁定不会发生冲突,因为一条记录一次只能由一个事务修改,一旦该行被修改锁定,锁将一直保留到事务提交或回滚。

只有明确的 LockModeType.OPTIMISTIC can lead to race conditions. However, you can easily fix that using a pessimistic shared or explicit lock.