我对JPA中的LockModeTypes的工作感到困惑:
LockModeType.Optimistic
LockModeType.OPTIMISTIC_FORCE_INCREMENT
LockModeType
的用途是什么。 LockModeType.PESSIMISTIC_READ
select for update nowait
(如果未指定提示超时)。Read
锁定? LockModeType.PESSIMISTIC_WRITE
select for update nowait
(如果未指定提示超时)。 LockModeType.PESSIMISTIC_READ
之间有什么区别,因为我看到两者都触发相同的查询? LockModeType.PESSIMISTIC_FORCE_INCREMENT
select for update nowait
(如果未指定提示超时),并且还会增加版本号。 for update no wait
,为什么需要版本增加? 最佳答案
首先,我将区分乐观锁和悲观锁,因为它们的底层机制不同。
乐观锁定完全由JPA控制,并且仅需要数据库表中的其他版本列。它完全独立于用于存储关系数据的基础数据库引擎。
另一方面,悲观锁定使用基础数据库提供的锁定机制来锁定表中的现有记录。 JPA需要知道如何触发这些锁定,并且某些数据库不支持或仅部分支持它们。
现在到锁类型列表:
LockModeType.Optimistic
LockModeType lockMode = resolveLockMode(); A a = em.find(A.class, 1, lockMode);
LockModeType.OPTIMISTIC_FORCE_INCREMENT
LockModeType.PESSIMISTIC_READ
LockModeType.PESSIMISTIC_WRITE
,但不同之处在于:在通过某种事务对同一实体进行写锁定之前,它不应阻止对实体的读取。它还允许其他事务使用LockModeType.PESSIMISTIC_READ
锁定。 here (ObjectDB)和here (OpenJPA)很好地解释了WRITE和READ锁之间的差异。如果一个实体已经被另一个事务锁定,则对其进行任何锁定尝试都会引发异常。可以将此行为修改为在引发异常并回滚事务之前等待一段时间以释放锁。为此,请在引发异常之前指定javax.persistence.lock.timeout
提示以及要等待的毫秒数。如Java EE tutorial中所述,有多种方法可以在多个级别上执行此操作。 LockModeType.PESSIMISTIC_WRITE
LockModeType.PESSIMISTIC_READ
的更强版本。当WRITE
锁定到位时,JPA在数据库的帮助下将阻止任何其他事务读取实体,而不仅仅是像READ
锁定那样进行写入。 READ
锁的功能。 SELECT...FOR UPDATE
实际上是WRITE
锁。这可能是休眠中的错误,或者是一个决定,它不是使用自定义的“较软”的READ
锁,而是使用“较硬”的WRITE
锁。这在大多数情况下不会破坏一致性,但是不会保留所有带有READ
锁的规则。您可以使用READ
锁和长时间运行的事务运行一些简单的测试,以了解是否有更多事务能够在同一实体上获取READ
锁。这应该是可能的,但不能使用WRITE
锁。 PESSIMISTIC
和OPTIMISTIC
机制的一种选择。在以下情况下,使用纯PESSIMISTIC_WRITE
可能会失败:LockModeType.PESSIMISTIC_FORCE_INCREMENT
将强制事务B更新版本号,并导致事务A失败,使用OptimisticLockException
,即使B使用悲观的锁定。