LockModeType Jpa 的区别 [英] Difference between LockModeType Jpa

查看:41
本文介绍了LockModeType Jpa 的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 JPA 中 LockModeTypes 的工作感到困惑:

I am confused about the working of LockModeTypes in JPA:

  1. LockModeType.Optimistic

  • 它在提交时增加版本.
  • 这里的问题是:如果我的实体中有 version 列,并且如果我没有指定此锁定模式,那么它的工作方式也类似,那么它的用途是什么?

LockModeType.OPTIMISTIC_FORCE_INCREMENT

  • 这里即使实体没有更新,它也会增加版本列.
  • 但是如果在提交此事务之前任何其他进程更新了同一行,它有什么用?这笔交易无论如何都会失败.那么这个LockModeType有什么用.

LockModeType.PESSIMISTIC_READ

  • 此锁定模式发出 select for update nowait(如果未指定提示超时)..
  • 所以基本上这意味着在提交此事务之前没有其他事务可以更新此行,那么它基本上是一个写锁,为什么将其命名为Read锁?
  • This lock mode issues a select for update nowait(if no hint timeout specified)..
  • so basically this means that no other transaction can update this row until this transaction is committed, then its basically a write lock, why its named a Read lock?

LockModeType.PESSIMISTIC_WRITE

  • 此锁定模式还会发出select for update nowait(如果未指定提示超时).
  • 这里的问题是这种锁定模式和 LockModeType.PESSIMISTIC_READ 之间有什么区别,因为我看到两者都触发了相同的查询?
  • This lock mode also issues a select for update nowait (if no hint timeout specified).
  • Question here is what is the difference between this lock mode and LockModeType.PESSIMISTIC_READ as I see both fires same queries?

LockModeType.PESSIMISTIC_FORCE_INCREMENT

  • 这会选择更新 nowait(如果没有指定提示超时)并且还会增加版本号.
  • 我完全没有使用它.
  • 如果更新无需等待,为什么需要版本增量?
  • this does select for update nowait (if no hint timeout specified) and also increments the version number.
  • I totally didn't get the use of it.
  • why a version increment is required if for update no wait is there?

推荐答案

我首先要区分乐观锁和悲观锁,因为它们的底层机制不同.

I would first differentiate between optimistic and pessimistic locks, because they are different in their underlying mechanism.

乐观锁完全由 JPA 控制,只需要在数据库表中添加版本列.它完全独立于用于存储关系数据的底层数据库引擎.

Optimistic locking is fully controlled by JPA and only requires additional version column in DB tables. It is completely independent of underlying DB engine used to store relational data.

另一方面,悲观锁定使用底层数据库提供的锁定机制来锁定表中的现有记录.JPA 需要知道如何触发这些锁,有些数据库不支持或仅部分支持.

On the other hand, pessimistic locking uses locking mechanism provided by underlying database to lock existing records in tables. JPA needs to know how to trigger these locks and some databases do not support them or only partially.

现在是锁类型列表:

  1. LockModeType.Optimistic
    • 如果实体指定了版本字段,则这是默认值.对于没有版本列的实体,不能保证使用这种类型的锁适用于任何 JPA 实现.如 ObjectDB 所述,这种模式通常会被忽略.在我看来,它的存在只是为了让您可以动态计算锁定模式并进一步传递它,即使锁定最终是乐观的.虽然不是很可能的用例,但提供一个选项来引用甚至默认值总是很好的 API 设计.
  1. LockModeType.Optimistic
    • If entities specify a version field, this is the default. For entities without a version column, using this type of lock isn't guaranteed to work on any JPA implementation. This mode is usually ignored as stated by ObjectDB. In my opinion it only exists so that you may compute lock mode dynamically and pass it further even if the lock would be OPTIMISTIC in the end. Not very probable usecase though, but it is always good API design to provide an option to reference even the default value.

  • 示例:

    • Example:

         `LockModeType lockMode = resolveLockMode();
       A a = em.find(A.class, 1, lockMode);`
      

      1. LockModeType.OPTIMISTIC_FORCE_INCREMENT

      • 这是一个很少使用的选项.但如果你想锁定另一个实体引用这个实体,这可能是合理的.换句话说,即使未修改实体,您也希望锁定与该实体的合作,但可能会修改与该实体相关的其他实体.
      • 示例:我们有实体 Book 和 Shelf.可以将书添加到书架,但书没有对其书架的任何引用.锁定将一本书移到书架的动作是合理的,这样一本书在本次交易结束之前不会在另一个书架上结束(由于另一笔交易).要锁定此操作,仅锁定当前书架实体是不够的,因为该书还不必在书架上.锁定所有目标书架也是没有意义的,因为它们在不同的交易中可能会有所不同.唯一有意义的是锁定书实体本身,即使在我们的例子中它没有被改变(它没有对其书架的引用).
        1. LockModeType.PESSIMISTIC_READ

        • 这种模式类似于LockModeType.PESSIMISTIC_WRITE,但有一点不同:直到某个事务在同一实体上写锁定到位,它不应该阻止读取实体.它还允许使用 LockModeType.PESSIMISTIC_READ 锁定其他事务.here (ObjectDB)此处(OpenJPA).如果一个实体已经被另一个事务锁定,任何锁定它的尝试都会引发异常.可以将此行为修改为等待一段时间释放锁,然后再抛出异常并回滚事务.为此,请指定 javax.persistence.lock.timeout 提示以及在抛出异常之前等待的毫秒数.有多种方法可以在多个级别执行此操作,如 Java EE 教程中所述.
          • this mode is similar to LockModeType.PESSIMISTIC_WRITE, but different in one thing: until write lock is in place on the same entity by some transaction, it should not block reading the entity. It also allows other transactions to lock using LockModeType.PESSIMISTIC_READ. The differences between WRITE and READ locks are well explained here (ObjectDB) and here (OpenJPA). If an entity is already locked by another transaction, any attempt to lock it will throw an exception. This behavior can be modified to waiting for some time for the lock to be released before throwing an exception and roll back the transaction. In order to do that, specify the javax.persistence.lock.timeout hint with the number of milliseconds to wait before throwing the exception. There are multiple ways to do this on multiple levels, as described in the Java EE tutorial.
            1. LockModeType.PESSIMISTIC_WRITE

            • 这是LockModeType.PESSIMISTIC_READ 的更强版本.当WRITE锁到位时,JPA在数据库的帮助下将阻止任何其他事务读取实体,而不仅仅是像READ锁那样写入.
            • 没有规定如何在 JPA 提供程序中与底层数据库合作实现这一点.在您使用 Oracle 的情况下,我会说 Oracle 没有提供接近 READ 锁的东西.SELECT...FOR UPDATE 实际上是一个 WRITE 锁.这可能是 hibernate 中的一个错误,或者只是一个决定,而不是实现自定义的更软"READ 锁,更难"的使用 WRITE 锁代替.这主要不会破坏一致性,但不会包含 READ 锁的所有规则.您可以使用 READ 锁和长时间运行的事务运行一些简单的测试,以确定是否有更多的事务能够在同一实体上获取 READ 锁.这应该是可能的,而使用 WRITE 锁则不行.
              • this is a stronger version of LockModeType.PESSIMISTIC_READ. When WRITE lock is in place, JPA with the help of the database will prevent any other transaction to read the entity, not only to write as with READ lock.
              • The way how this is implemented in a JPA provider in cooperation with underlying DB is not prescribed. In your case with Oracle, I would say that Oracle does not provide something close to a READ lock. SELECT...FOR UPDATE is really rather a WRITE lock. It may be a bug in hibernate or just a decision that, instead of implementing custom "softer" READ lock, the "harder" WRITE lock is used instead. This mostly does not break consistency, but does not hold all rules with READ locks. You could run some simple tests with READ locks and long running transactions to find out if more transactions are able to acquire READ locks on the same entity. This should be possible, whereas not with WRITE locks.
                1. LockModeType.PESSIMISTIC_FORCE_INCREMENT

                • 这是另一种很少使用的锁定模式.但是,它是您需要结合 PESSIMISTICOPTIMISTIC 机制的选项.在以下情况下使用普通 PESSIMISTIC_WRITE 会失败:

                  • this is another rarely used lock mode. However, it is an option where you need to combine PESSIMISTIC and OPTIMISTIC mechanisms. Using plain PESSIMISTIC_WRITE would fail in following scenario:

                    1. 事务 A 使用乐观锁定并读取实体 E
                    2. 事务 B 获得实体 E 的 WRITE 锁
                    3. 事务 B 提交并释放 E 的锁
                    4. 事务 A 更新 E 并提交

                  • 在第 4 步中,如果 version 列没有被事务 B 递增,则没有什么可以阻止 A 覆盖 B 的更改.锁定模式 LockModeType.PESSIMISTIC_FORCE_INCREMENT 将强制事务 B 更新版本号并导致事务 A以 OptimisticLockException 失败,即使 B 使用悲观锁定.
                  • in step 4, if version column is not incremented by transaction B, nothing prevents A from overwriting changes of B. Lock mode LockModeType.PESSIMISTIC_FORCE_INCREMENT will force transaction B to update version number and causing transaction A to fail with OptimisticLockException, even though B was using pessimistic locking.
                    1. LockModeType.NONE

                    • 如果实体不提供版本字段,则这是默认设置.这意味着未启用锁定冲突将尽最大努力解决并且不会被检测到.这是在事务之外允许的唯一锁定模式
                    • 这篇关于LockModeType Jpa 的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆