JPA实体锁定模式的差异

JPA本质上提供了两种锁定机制,以帮助同步对实体的访问。 两种机制都可以防止以下情况:两个事务在不知道的情况下相互覆盖数据。

通过实体锁定,我们通常希望通过2个并行事务来防止以下情况:

  1. 亚当的事务读取数据X
  2. 芭芭拉的交易读取数据X
  3. 亚当的交易会修改数据X,并将其更改为XA
  4. 亚当的事务将数据写入XA
  5. 芭芭拉的交易修改了数据X并将其更改为XB
  6. 芭芭拉的交易写数据XB

结果,亚当所做的更改完全被芭芭拉(Barbara)所取代,甚至没有引起她的注意。 像这样的场景有时被称为脏读 。 显然,理想的结果是Adam编写XA,而Barbara被迫在编写XB之前检查XA更改。

乐观锁的工作原理

乐观锁定基于这样的假设:冲突非常少见;如果发生冲突,则抛出错误是可以接受的,并且比防止冲突更方便。 允许其中一项交易正确完成,但其他任何交易都会例外回滚,并且必须重新执行或丢弃。

通过乐观锁定,亚当和芭芭拉可能出现以下情况:

  1. 亚当的事务读取数据X
  2. 芭芭拉的交易读取数据X
  3. 亚当的交易会修改数据X,并将其更改为XA
  4. 亚当的事务将数据写入XA
  5. 芭芭拉的交易修改了数据X并将其更改为XB
  6. Barbara的事务尝试写入数据XB,但接收到并出错
  7. 芭芭拉需要读取数据XA(或开始全新的交易)
  8. Barbara的事务修改了数据XA并将其更改为XAB
  9. Barbara的事务写入数据XAB

如您所见,芭芭拉被迫审查亚当的更改,如果她决定,她可能会修改亚当的更改并保存(合并更改)。 最终数据包含亚当和巴巴拉的变化。

JPA完全控制乐观锁定。 它需要数据库表中的其他版本列。 它完全独立于用于存储关系数据的基础数据库引擎。

悲观锁定如何工作

对于某些人来说,悲观锁定被认为是很自然的。 当事务需要修改实体(可以由另一个事务并行修改)时,事务将发出锁定该实体的命令。 所有锁将保留到事务结束,然后自动释放。

使用悲观锁,情况可能是这样的:

  1. 亚当的事务读取数据X
  2. 亚当的交易锁定X
  3. 芭芭拉的交易想要读取数据X,但是等待X已被锁定
  4. 亚当的交易会修改数据X,并将其更改为XA
  5. 亚当的事务将数据写入XA
  6. 芭芭拉的交易读取数据XA
  7. Barbara的事务修改了数据XA并将其更改为XAB
  8. Barbara的事务写入数据XAB

如我们所见,Barbara再次被迫编写XAB,其中也包含Adam所做的更改。 但是,该解决方案与乐观方案完全不同–芭芭拉需要等待亚当的交易完成后才能读取数据。 此外,我们需要在两个事务中手动发出锁定命令,以使该方案起作用。 (由于我们不确定亚当或芭芭拉首先要处理哪个事务,因此两个事务都需要在修改数据之前先锁定数据。)乐观锁定比悲观锁定需要更多的设置,每个实体都需要使用version列,但随后我们不需要记住在交易中发出锁。 JPA自动执行所有检查,我们只需要处理可能的异常。

悲观锁定使用基础数据库提供的锁定机制锁定表中的现有记录。 JPA需要知道如何触发这些锁定,并且某些数据库不完全支持。

甚至JPA规范都说,不需要提供PESSIMISTIC_READ(因为许多数据库仅支持WRITE锁):

这是允许的,以使用实施LockModeType.PESSIMISTIC_WRITE其中LockModeType.PESSIMISTIC_READ请求,而不是相反。

JPA中可用锁类型的列表

首先,我想说的是,如果实体中提供了@Version列,则JPA会默认为此类实体打开乐观锁定。 您不需要发出任何锁定命令。 但是,您可以随时使用以下一种锁类型发出锁:

  1. LockModeType.Optimistic
    • 这确实是默认设置。 如ObjectDB所述,通常将其忽略。 在我看来,它只是存在的,这样您就可以动态地计算锁定模式,即使锁定最终是最优的,也可以进一步传递它。 虽然用例不是很可能,但是提供一个甚至引用默认值的选项也是一种很好的API设计。
    • 示例:Java
      LockModeType lockMode = resolveLockMode();
      A a = em.find(A.class, 1, lockMode);
  2. LockModeType.OPTIMISTIC_FORCE_INCREMENT
    • 这是很少使用的选项。 但是,如果您想锁定另一个实体对这个实体的引用,这可能是合理的。 换句话说,即使您未修改某个实体,您也希望锁定该实体的工作,但是其他实体也可能相对于该实体而被修改。
    • 例:
      • 我们有实体书和书架。 可以将Book添加到书架中,但是book没有对其书架的引用。 锁定将书移动到书架上的操作是合理的,这样一本书不会最终出现在两个书架中。 要锁定此操作,仅锁定当前书架实体是不够的,因为书还不必在书架上。 锁定所有目标书架也没有意义,因为它们在不同交易中可能会有所不同。 唯一有意义的是锁定书本实体本身,即使在我们这种情况下它没有被更改(它不保留对其书架的引用)。
  3. LockModeType.PESSIMISTIC_READ
    • 此模式类似于LockModeType.PESSIMISTIC_WRITE ,但有一点不同:在通过某种事务在同一实体上施加写锁定之前,它不应阻止读取实体。 它还允许其他事务使用LockModeType.PESSIMISTIC_READ锁定。 WRITE和READ锁之间的区别在这里(ObjectDB)和这里(OpenJPA)都有很好的解释。 但是,由于规范允许,很多情况下,它的行为类似于LockModeType.PESSIMISTIC_WRITE ,许多提供程序并未单独实现它。
  4. LockModeType.PESSIMISTIC_WRITE
    • 这是LockModeType.PESSIMISTIC_READ的增强版本。 有了WRITE锁定后,JPA借助数据库将阻止任何其他事务读取该实体,而不仅仅是像READ锁定那样进行写入。
  5. LockModeType.PESSIMISTIC_FORCE_INCREMENT
    • 这是另一种很少使用的锁定模式。 但是,这是您需要结合PESSIMISTICOPTIMISTIC机制的一种选择。 在以下情况下,使用普通的PESSIMISTIC_WRITE可能会失败:
      1. 事务A使用乐观锁定并读取实体E
      2. 事务B获得对实体E的WRITE锁定
      3. 事务B提交并释放E的锁
      4. 事务A更新E并提交
    • 在第4步中,如果版本B未被事务B递增,则不会阻止A覆盖B的更改。锁定模式LockModeType.PESSIMISTIC_FORCE_INCREMENT将强制事务B更新版本号,并导致事务A以OptimisticLockException失败,即使B正在使用悲观的锁定。

为了发出某种类型的锁,JPA提供了以下方法:

  • 一些EntityManager方法接受一个可选参数来指定锁定类型,例如:
    • find(类entityClass,Object primaryKey,LockModeType lockMode)
  • 查询还提供setLockMode(LockModeType lockMode)方法来锁定将由查询检索的所有实体

您可以在JPA中使用两种类型的锁定机制中的任何一种。 如果您使用类型PESSIMISTIC_FORCE_INCREMENT悲观锁,也可以在必要时将它们混合使用。

  • 要了解更多信息,请阅读Vlad Mihalcea的优秀博客。

翻译自: https://www.javacodegeeks.com/2016/02/differences-jpa-entity-locking-modes.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/354948.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java虚拟机源码怎么看_java虚拟机JVM第4讲:从源代码到机器码,发生了什么?

在上篇文章我们聊到,无论什么语言写的代码,其到最后都是通过机器码运行的,无一例外。那么对于 Java 语言来说,其从源代码到机器码,这中间到底发生了什么呢?这就是今天我们要聊的。如下图所示,编…

array reduce

[1, 2, 3].reduce((total, n) > {console.log(total, n) return total n; }, 10); 转载于:https://www.cnblogs.com/yangwenzhi/p/7427881.html

java构建内存池队列_池化技术(线程池、连接池、内存池等)

一、池化技术 -简单点来说,就是提前保存大量的资源,以备不时之需。对于线程,内存,oracle的连接对象等等,这些都是资源,程序中当你创建一个线程或者在堆上申请一块内存时,都涉及到很多系统调用&a…

java 堆大小_适当的Java堆大小的5个技巧

java 堆大小确定生产系统合适的Java堆大小不是一件容易的事。 在我的Java EE企业经验中,由于Java堆容量和调整不足,我遇到了多个性能问题案例。 本文将为您提供5个技巧,这些技巧可以帮助您确定当前或新生产环境的最佳Java堆大小。 这些技巧中…

jcmd:一个可以全部统治的JDK命令行工具

我在过去的几篇文章中都引用了方便的JDK工具jcmd ,但是像我以前对jps所做的那样,仅专注于其实用性 。 jcmd工具是随Oracle Java 7引入的,在通过使用Java标识Java进程的ID (与jps相似),获取堆转储 &#xff…

普通java程序怎样用cron_java – Spring cron vs普通cron?

我正在尝试在遗留的Java / Spring / Hibernate项目中使用cron作业,所以我决定使用spring调度程序.我希望myTask.doStuff在每个月的第一个星期日的12:00运行.在我的application-context.xml中,我已经将我的任务调度程序配置为:问题cron表达本身是:0 0 12&…

ansible-playbook实操之一键搭建lnmp+wordpress

目录 1、架构和准备: 2、配置nginx角色: 3、配置mariadb角色: 4、配置php角色: 5、配置完之后,写脚本调用roles 6、配置完之后浏览器搭建wordpress: 1、架构和准备: 操控节点:…

pivot 与 unpivot 函数是SQL05新提供的2个函数

pivot 与 unpivot 函数是SQL05新提供的2个函数 ------------------------------------------------------------------------------ pivot函数: create table test(id int,name varchar(20),quarter int,profile int)insert into test values(1,a,1,1000)insert i…

java职业教育考试题_Java认证考试中Java构造方法题目解答

【Java认证考试中Java构造方法题目解答】java中,在创建一个新的对象的时候,会调用其父亲的构造方法,测试程序如下:class parent{int a5;public parent(){System.out.println("a"a);System.out.println("parent()&q…

jsf集成spring_Spring和JSF集成:异常处理

jsf集成spring大多数JSF开发人员都会熟悉“发生错误”页面,当在他们的代码某处引发意外异常时,该页面就会显示。 该页面在开发时确实很有用,但对于生产应用程序通常不是您想要的。 通常,在使用库存JSF替换此页面时,通常…

python SimpleHTTPServer 快速共享文件

简单介绍 通过一个python命令快速共享文件给他人。 操作步骤 1、打开cmd命令行,切换到需要共享文件的目录,执行命令 python -m SimpleHTTPServer 。 2、打开浏览器,在地址栏中输入http://10.10.11.164:8000或者http://localhost:8000/可以看到…

mysql数据库设计实现工作流_工作流activiti部署到数据库(1)

1.工作流定义(workflow):指"业务过程的部分或整体在计算机应用环境下的自动化".普通框架要有一个请假单,要有一个字段来标识请假单的状态,至少有三个,还有请假单的状态是走到那个经理审批还是老板审批,这个时候不便管理.BPM:业务流程管理框架,是用来管理流程的框架.B…

Java EE安全性API向前发展

Java EE安全API( JSR 375 )正在向前发展,正如Arjan Tijms在此处概述的那样 : http : //arjan-tijms.omnifaces.org/p/whats-new-in-java-ee-security-api-10 。 html 。 需要注意的一件事是,我们现在为参考实现有了一…

程序员应该多逛的几个技术网站

1、stack overflow 2、github 3、csdn 4、osChina 5、xitu.io 6、www.infoQ.com 7、www.ctolib.com 8、慕课 9、知乎 10、博客园 转载于:https://www.cnblogs.com/qq666666/p/7439705.html

abd.exe 需要下java吗_Abd.exe文件下载|

abd.exe在哪个位置?abd.exe是一款很重要的电脑文件,如果这个文件丢失了,电脑部分程序将会无法正常运行,所以大家应该重视这类文件,小编已经将这个文件打包好了,欢迎大家来当易网下载。exe文件简介EXE File …

resteasy_RESTEasy教程第1部分:基础

resteasyRESTEasy是来自JBoss / RedHat的JAX-RS实现&#xff0c;并且内置于JBoss 6之后。 在这里&#xff0c;我将向您展示如何使用RESTEasy和JBossAS7.1.1.FINAL开发一个简单的RESTful Web服务应用程序。 步骤&#xff03;1&#xff1a;使用Maven配置RESTEasy依赖项。 <pro…

Spark面对OOM问题的解决方法及优化总结 (转载)

Spark面对OOM问题的解决方法及优化总结 (转载) 转载地址&#xff1a; http://blog.csdn.net/yhb315279058/article/details/51035631 Spark中的OOM问题不外乎以下两种情况map执行中内存溢出shuffle后内存溢出map执行中内存溢出代表了所有map类型的操作&#xff0c;包括&#xf…

java数据抽取到数据仓库_关于数据增量抽取的模拟实现——脚本实现

具体排过版的请参看http://Percywang.itpub.net本文主要是针对关于数据增量抽取的模拟实现——原理进行实现的实现的环境&#xff1a;业务数据库&#xff1a;Oracle9i数据仓库数据库&#xff1a;SQLServer20001、前提SQLServer服务器已经安装Oracle驱动&#xff0c;不再详细累述…

通过此注释改善您的JUnit体验

JUnit可能是所有Java项目中90&#xff05;的一部分。 令人兴奋的是&#xff0c;我们很快将拥有支持Java 8的JUnit 5 。 我们最近在博客上发表了一项改进 。 回到JUnit 4领域&#xff0c;有一个小技巧&#xff0c;我只能建议您进行所有单元测试。 只需在此处添加这个小注释&…

HDU 3555 Bomb (数位DP)

数位dp,主要用来解决统计满足某类特殊关系或有某些特点的区间内的数的个数&#xff0c;它是按位来进行计数统计的&#xff0c;可以保存子状态&#xff0c;速度较快。数位dp做多了后&#xff0c;套路基本上都差不多&#xff0c;关键把要保存的状态给抽象出来&#xff0c;保存下来…