当前位置: 首页 > 面试题库 >

Jpa LockModeType之间的区别

韩寂离
2023-03-14
问题内容

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

  1. LockModeType.Optimistic

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

    • 即使未更新实体,它也会在此处增加版本列。

    • 但是,如果在提交此事务之前有任何其他进程在同一行中进行了更新,它的用途是什么?无论如何,该交易将失败。那么这个有什么用呢LockModeType
    • LockModeType.PESSIMISTIC_READ

    • 此锁定模式发出a 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需要知道如何触发这些锁定,并且某些数据库不支持或仅部分支持它们。

现在到锁类型列表:

  1. LockModeType.Optimistic

    • 如果实体指定版本字段,则这是默认值。对于没有版本列的实体,不能保证在任何JPA实现中都不能使用这种类型的锁。如ObjectDB所述,通常会忽略此模式。在我看来,它只是存在的,这样您就可以动态地计算锁定模式,即使锁定最终是最优的,也可以进一步传递它。虽然用例不是很可能,但是提供一个甚至引用默认值的选项也是一种很好的API设计。
    • 例:

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

  1. LockModeType.OPTIMISTIC_FORCE_INCREMENT

    • This is a rarely used option. But it could be reasonable, if you want to lock referencing this entity by another entity. In other words you want to lock working with an entity even if it is not modified, but other entities may be modified in relation to this entity.
    • 示例:我们有实体书和书架。可以将Book添加到书架中,但是book没有对其书架的引用。锁定将书移动到书架上的操作是合理的,这样一本书在此交易结束之前不会落在另一个书架中(由于另一笔交易)。要锁定此操作,仅锁定当前书架实体是不够的,因为书还不必在书架上。锁定所有目标书架也没有意义,因为它们在不同交易中可能会有所不同。唯一有意义的是锁定书本实体本身,即使在我们这种情况下它没有被更改(它不保留对其书架的引用)。
    • LockModeType.PESSIMISTIC_READ

    • 此模式与相似LockModeType.PESSIMISTIC_WRITE,但有一点不同:在通过某种事务在同一实体上施加写锁定之前,它不应阻止读取实体。它还允许使用锁定其他事务LockModeType.PESSIMISTIC_READ。WRITE和READ锁之间的区别在这里(ObjectDB)和这里(OpenJPA)都有很好的解释。如果一个实体已经被另一个事务锁定,则对其进行任何锁定尝试都将引发异常。可以将此行为修改为在引发异常并回滚事务之前等待一段时间以释放锁。为此,javax.persistence.lock.timeout请在引发异常之前指定提示以毫秒为单位。有多种方法可以在多个级别上执行此操作,如Java EE教程。

    • LockModeType.PESSIMISTIC_WRITE

    • 这是的更强版本LockModeType.PESSIMISTIC_READ。当WRITE锁定到位时,JPA在数据库的帮助下将阻止任何其他事务读取实体,而不仅仅是像READ锁定时一样进行写入。

    • 没有规定如何在JPA提供程序中与基础DB合作实现此方法。对于Oracle,我想说Oracle不能提供接近READ锁的功能。SELECT...FOR UPDATE确实是一个WRITE锁。这可能是hibernate中的错误,或者是一个决定,而不是实现自定义的“较软” READ锁,WRITE而是使用了“较硬” 锁。这在大多数情况下不会破坏一致性,但是不会保留所有READ带锁的规则。您可以使用READ锁和长时间运行的事务运行一些简单的测试,以了解是否有更多事务能够READ在同一实体上获取锁。这应该是可能的,但不能使用WRITE锁。
    • LockModeType.PESSIMISTIC_FORCE_INCREMENT

    • 这是另一种很少使用的锁定模式。但是,这是您需要结合使用PESSIMISTICOPTIMISTIC机制的一种选择。PESSIMISTIC_WRITE在以下情况下,使用Plain 将失败:

    • 事务A使用乐观锁定并读取实体E
    • 事务B获得对实体E的WRITE锁定
    • 事务B提交并释放E的锁
    • 事务A更新E并提交
    • 在第4步中,如果版本B未被事务B增加,则没有什么阻止A覆盖B的更改。锁定模式LockModeType.PESSIMISTIC_FORCE_INCREMENT将强制事务B更新版本号,并导致事务A失败OptimisticLockException,即使B使用悲观锁定。
    • LockModeType.NONE

    • 如果实体不提供版本字段,则为默认设置。这意味着没有启用锁定,将尽力解决冲突,并且不会检测到冲突。这是事务外部唯一允许的锁定模式



 类似资料:
  • 我不理解 如果a是假的,那么b是看的,但是条件没有被测试。 但。。。。 现在,如果a为真,那么b不被查看,条件不被测试。 这是为什么。我以为这个的目的 我有这个权利吗?如果我有,为什么会这样?

  • 问题内容: 我错放了太多次了,我想我一直忘记,因为我不知道两者之间的区别,只是一个给了我我期望的价值,而另一个却没有。 为什么是这样? 问题答案: 是的简写形式(尽管请注意,该表达式只会被计算一次。) 是的,即指定一元的到。 例子:

  • 问题内容: 因此,我有一段简单的代码可以打印出整数1-10: 然后,如果仅在第3行上更改一个运算符,它将打印出无限数量的1整数(我知道为什么会这样做)。为什么在运行第二个程序时没有出现语法错误?如果赋值运算符后面跟着一个加法运算符,它不会调用语法错误吗? 问题答案: 与相同, 只是意味着。

  • 问题内容: 有人可以解释一下 和 我不知道“确切”的含义 问题答案: 在这个例子中,什么都没有。当您具有多个具有相似名称的路径时,该参数将起作用: 例如,假设我们有一个显示用户列表的组件。我们还有一个用于创建用户的组件。的网址应嵌套在下。因此,我们的设置可能如下所示: 现在,这里的问题是,当我们转到路由器时,将通过所有定义的路由,并返回它找到的第一个匹配项。因此,在这种情况下,它将首先找到路线,然

  • 我有一组不重叠的,不相邻的区间,例如[{10,15},{30,35},{20,25}]。它们没有排序,但如果需要,我可以对它们进行排序。 现在,我得到了一些新的区间,例如{5,32},并希望生成一组新的区间来描述差异:这个新区间所覆盖的范围不在该集合中。在这个例子中,答案是:[{5,9},{16,19},{26,29}]。 计算这个的快速算法是什么?请注意,集合中通常有1个,有时有2个,很少有3个