高并发问题是程序设计所必须要解决的问题,解决此类问题最主要的途径就是对对程序进行加锁控制。hibernate对加锁机制同样做出了实现,常用加锁方式为悲观锁和乐观锁。悲观锁指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态,通常是由数据库机制实现的,在整个过程中把数据锁住(查询时),只要事务不释放(提交或者回滚)任何用户都不能查看或修改。

悲观锁的应用:

悲观锁的应用十分的简单,如果使用get或load方法进行查询,只需要将load/get方法的第三个参数LockMode设置为UPGRADE就可以了,使用这个参数后我们每次发送的SQL语句都会加上"for update"用于告诉数据库锁定相关数据。如:         Inventory inv =(Inventory)session.load(Inventory.class, "1001", LockMode.UPGRADE);。如果直接使用hql语句的话,可以在语句的末尾加入for update,如:select s from Student s where s.name=”张三” for update,这条语句的末尾加入forupdate 后所有name为“张三”的数据都将会被锁定。

虽然悲观锁在Hibernate中应用十分容易,但在实际应用中使用悲观锁的情况并不多,因为它大大限制了程序的并发性,如果查询过程时间过长会给客户带来极其不好的体验。

乐观锁的应用:

其实与其说加锁不如说它更像是一种版本检测工具,其工作原理是这样的:需要在数据表中添加一个version字段,当读出数据的时候会将该字段的值一并读出,在进行更新操作的时候会将此版本号加一,然后对比新的版本号与数据库表中的版本号,如果新提交的版本号不大于数据表中的版本号则会被认为是过期数据不予更新,否则则进行数据更新。相对于悲观锁来讲乐观锁的加锁机制更加宽松,而且由于乐观锁是基于数据库表的版本解决方案,并不像悲观锁依靠于数据库的锁机制保证操作的最大独占性(会增加数据库的性能开销),所以乐观锁在实际中的应用要远远多于悲观锁。Hibernate对于乐观锁提供了三种实现,他们分别是:

1.      基于version

2.      基于timestamp

3.      基于遗留项目

其中前两种的原理是一样的,一个是以数字1,2,3…作为版本标识,而另一个是以时间作为版本标识而已,但应注意一顶要把version标签(或timestamp标签)放到id的下面而且要紧邻id。我们以version为例,在映射文件中做如下配置:

  1. <hibernate-mapping>
  2. <class name="com.bjpowernode.hibernate.Inventory" table="t_inventory" optimistic-lock="version" >
  3. <id name="itemNo">
  4. <generator class="assigned"/>
  5. </id>
  6. <version name="version"/>
  7. <!--<timestamp name="updateDate"/> -->
  8. <property name="itemName"/>
  9. <property name="quantity"/>
  10. </class>
  11. </hibernate-mapping>

如果要换成第二种,只要把映射文件中的version标签换成timestamp标签就可以了(当然需要在实体类中加入相应的成员变量)。

那什么又叫基于遗留项目的乐观锁呢?由于各种原因无法为原有的数据库添加"version"或"timestamp"字段,这时不可以使用上面方式配置乐观锁,Hibernate为这种情况提供了一个"optimisitic-lock"属性,它位于<class>标签上,同时必须设置optimistic-lock属性值为all并且设置dynamic-update属性值为true。设置了这种乐观锁与前两种相比不再是根据vsersion版本号或者时间戳的不同来判断是否是最新数据,而是根据表中所有字段来判断是否是最新数据,只要有任意一个字段的值发生了变化,就会被认为是过期数据不予提交。

它的配置文件是这样的:

  1. <hibernate-mapping>
  2. <class name="com.bjpowernode.hibernate.Inventory" table="t_inventory" optimistic-lock="all" dynamic-update="true">
  3. <id name="itemNo">
  4. <generator class="assigned"/>
  5. </id>
  6. <!-- <version name="version"/> -->
  7. <!--<timestamp name="updateDate"/> -->
  8. <property name="itemName"/>
  9. <property name="quantity"/>
  10. </class>
  11. </hibernate-mapping>

至此我们介绍完了Hibernate中悲观锁和乐观锁的实现,希望对大家进一步理解乐观锁和悲观锁有所帮助。

Hibernate解决高并发问题之:悲观锁 VS 乐观锁的更多相关文章

  1. 使用数据库乐观锁解决高并发秒杀问题,以及如何模拟高并发的场景,CyclicBarrier和CountDownLatch类的用法

    数据库:mysql 数据库的乐观锁:一般通过数据表加version来实现,相对于悲观锁的话,更能省数据库性能,废话不多说,直接看代码 第一步: 建立数据库表: CREATE TABLE `skill_ ...

  2. 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存

    原文:http://blog.csdn.net/heyewu4107/article/details/71009712 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问 ...

  3. PHP利用Mysql锁解决高并发

    前面写过利用文件锁来处理高并发的问题的,现在我们说另外一个处理方式,利用Mysql的锁来解决高并发的问题 先看没有利用事务的时候并发的后果 创建库存管理表 CREATE TABLE `storage` ...

  4. 利用redis实现分布式事务锁,解决高并发环境下库存扣减

    利用redis实现分布式事务锁,解决高并发环境下库存扣减   问题描述: 某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 解决方案一 利用数据 ...

  5. java解决高并发问题

    对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了.而并发问题是绝大部分的程序员头疼的问题, 但话又说回来了,既然逃避不掉,那我们就坦然面对吧~今天就让我们一起来研 ...

  6. 025 hibernate悲观锁、乐观锁

    Hibernate谈到悲观锁.乐观锁,就要谈到数据库的并发问题,数据库的隔离级别越高它的并发性就越差 并发性:当前系统进行了序列化后,当前读取数据后,别人查询不了,看不了.称为并发性不好 数据库隔离级 ...

  7. Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS

    首先介绍一些乐观锁与悲观锁: 悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁.传统的关系型数据库里边就用到了很 ...

  8. Hibernate 再接触 悲观锁和乐观锁

    为什么取1248 二进制 CRUD 移位效率高 在并发和效率选择一个平衡点 一般不会考虑幻读 因为我们不会再一个事务里查询两次,(只能设置为seralizable) 悲观锁和乐观锁的前提是read-u ...

  9. 转发:php解决高并发

    php解决高并发(转发:https://www.cnblogs.com/walblog/articles/8476579.html) 我们通常衡量一个Web系统的吞吐率的指标是QPS(Query Pe ...

随机推荐

  1. Opencv 的数据结构

    opencv的基本数据结构 结构 成员 意义 CvPoint int x,y 图像中的点 CvPoint2D32f float x,y 二维空间中的点 CvPoint3D32f float x,y,z ...

  2. WPF如何卸载U盘(弹出USB设备)

    应用程序和硬件设备的通信过程是:应用程序使用CreateFile函数打开设备,然后用DeviceIoControl()与硬件设备通信. CreateFile函数: [DllImport("k ...

  3. (转)Mac OS X内核编程,MAC驱动开发资源汇总

    一.Mac  OS  X内核编程开发官方文档: I/O Kit Fundamentals: I/O Kit基础 - Mac OS X系统内核编程 https://developer.apple.com ...

  4. FPGA串口波特率简析

    以前用单片机,一直都是直接用就行,设置波特率时,直接写9600就行,一直没有仔细考虑过,今天打算用FPGA写个串口程序时才知道,原来根本就是没弄明白.一下是我的一些见解.如果诸位看官觉得不对,欢迎指正 ...

  5. UVA 725

    Description   Write a program that finds and displays all pairs of 5-digit numbers that between them ...

  6. css3 旋转效果加上双面显示效果

    在学习Css3的过程中,我想做一个类似金字塔,菱形翻页效果,如图这种效果 如是,我自己设计了一个,不带js的旋转效果: 1>第一步我先设计了一个方块,内含一个旋转了45deg的小方块,代码如下: ...

  7. dnf的动画脚本研究

    . 1.0x00    : 帧数           int16 2.0x02    : 总为1(?) int16 3.0x04  : 资源文件名长度 int32 4.长度+1 :   0,1(未知用 ...

  8. C#学习笔记---基础入门(二)

    枚举 枚举是被命名的整型常数的集合:枚举类型的变量只有赋值后才能使用:不同枚举中的枚举值可以重名:可以自定义枚举值. enum Playstates {            跑, 跳,下滑,左转,右 ...

  9. 动态内存 this指针

    #include <iostream> #include <string> class Company { public: Company(std::string theNam ...

  10. 动态链接库中分配内存引起的问题-- windows已在XX.exe中触发一个断点

    动态链接库中分配内存引起的 本文主要是探讨关于在动态链接库分配的内存在主程序中释放所产生的问题,该问题是我在刚做的PJP工程中所遇到的,由于刚碰到之时感动比较诡异(这也是学识不够所致),所以将它写下来 ...