1、悲观锁

它指的是对数据被外界修改保持保守态度,因些,在整个数据处理过程中,将数据牌锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层的锁机制才能保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。

一个典型的悲观锁调用示例:

select * from account where name = "12345" for update

通过for update子句,这条SQL锁定了account表中所有符合检索条件的记录。本次事务提交之前(事务提交时会释放事务过程中的锁),外界无法修改这些记录。

2、乐观锁

相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制,以操作最大程度的独占性。但随着而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。

乐观锁,大多是基于数据版本(Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于库表的版本解决方案中,一般是通过为数据库表增加version字段来实现。

读取出数据时,将此版本号一同读出,之生更新时,对此版本号加1.此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。

例如,两个人同时在同一个帐号取钱,账号有100,A取50,B取20,A先提交,B的余额即为80,这时就不同步了,A提交后版本已经变了2了,而B看到的还是1的版本,此时B的提交必须被驳回。

需要注意的是,乐观锁机制往往基于系统中的数据存储逻辑,因此也具备一定的局限性。如有些例子,由于乐观锁机制是在我们的系统中实现,来自外部系统的用户余额更新操作不受我们系统控制,因此可能会造成非法数据被更新到数据库中。

在系统设计阶段,我们应该充分考虑到某些情况出现的可能性,并进行相应调整(如将乐观锁策略在数据库存储过程中实现,对外只开放基于此存储过程的数据更新途径,而不是将数据库表直接对外公开)。

Hibernate 在其数据访问引擎中内置了乐观锁实现。如果不用考虑外部系统对数据库的更新操作,利用Hibernate提供的透明化乐观锁实现,将大大提升我们的生产力。

(1)、实体类

  1. package learn.hibernate.bean;
  2.  
  3. import java.util.Date;
  4. import java.util.HashSet;
  5. import java.util.Set;
  6.  
  7. /**
  8. * 持久化类设计
  9. * 注意:
  10. * 持久化类通常建议要有一个持久化标识符(ID)
  11. * 持久化标识符通常建议使用封装类(例如:Integer 因为基本类型存在默认值)
  12. * 持久化类通常建议手动添加一个无参构造函数 (因为有些操作是通过放射机制进行的)
  13. * 属性通常建议提供 getter/setter 方法
  14. * 持久化类不能使用 final 修饰
  15. * 持久化类中如果使用了集合类型数据,只能使用集合所对应的接口类型来声明(List/Map/Set)
  16. * 如下:ArrayList list = new ArrayList(); 不行
  17. * List list = new ArrayList(); 可行
  18. */
  19. public class Person {
  20.  
  21. private Integer id;
  22. private String name;
  23. private int age;
  24. private int passwork;
  25. private Date birthday;
  26. private Integer version;
  27.  
  28. public Person() {
  29.  
  30. }
  31.  
  32. public Person(String name, int age, int passwork, Date birthday) {
  33. super();
  34. this.name = name;
  35. this.age = age;
  36. this.passwork = passwork;
  37. this.birthday = birthday;
  38. }
  39.  
  40. @Override
  41. public String toString() {
  42. return "Person [id=" + id + ", name=" + name + ", age=" + age
  43. + ", passwork=" + passwork + ", birthday=" + birthday + "]";
  44. }
  45.  
  46. public Integer getId() {
  47. return id;
  48. }
  49. public void setId(Integer id) {
  50. this.id = id;
  51. }
  52. public String getName() {
  53. return name;
  54. }
  55. public void setName(String name) {
  56. this.name = name;
  57. }
  58. public int getAge() {
  59. return age;
  60. }
  61. public void setAge(int age) {
  62. this.age = age;
  63. }
  64. public int getPasswork() {
  65. return passwork;
  66. }
  67. public void setPasswork(int passwork) {
  68. this.passwork = passwork;
  69. }
  70. public Date getBirthday() {
  71. return birthday;
  72. }
  73. public void setBirthday(Date birthday) {
  74. this.birthday = birthday;
  75. }
  76.  
  77. public Integer getVersion() {
  78. return version;
  79. }
  80.  
  81. public void setVersion(Integer version) {
  82. this.version = version;
  83. }
  84. }

(2)、持久化映射文件

  1. <?xml version="1.0"?>
  2. <!DOCTYPE hibernate-mapping PUBLIC
  3. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  4. "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
  5. <hibernate-mapping package="learn.hibernate.bean">
  6. <!--
  7. optimistic-lock="version" 指定持久化类的乐观锁策略
  8. -->
  9. <class name="Person" table="t_person" optimistic-lock="version">
  10. <id name="id" column="person_id">
  11. <generator class="native"/>
  12. </id>
  13. <!-- 配置 锁字段和对应的属性关联,以及字段类型 -->
  14. <version name="version" column="t_version" type="integer"/>
  15. <property name="name" column="t_name"/>
  16. <property name="age"/>
  17. <property name="passwork"/>
  18. <property name="birthday"/>
  19. </class>
  20. </hibernate-mapping>

(3)、测试类

  1. /**
  2. * hibernate 在获取数据的时候返回一个锁状态
  3. * 在提交数据的时候会自动的将锁状态进行改变
  4. */
  5. @Test
  6. public void testUpdate(){
  7. Person p1 = (Person)s1.get(Person.class, 1);
  8. Person p2 = (Person)s2.get(Person.class, 1);
  9.  
  10. System.out.println("----------1---start-----------");
  11. tx = s1.beginTransaction();
  12. p1.setName("p1");
  13. s1.update(p1);
  14. tx.commit();
  15. System.out.println("----------1---end-----------");
  16.  
  17. System.out.println("----------2---start-----------");
  18. tx = s2.beginTransaction();
  19. p2.setName("p2");
  20. s2.update(p2);
  21. tx.commit();
  22. System.out.println("----------2---end-----------");
  23. }

可以查看:http://blog.csdn.net/shen516/article/details/8599068

Hibernate学习---第十二节:Hibernate之锁机制&乐观锁实现的更多相关文章

  1. Mysql锁机制--乐观锁 & 悲观锁

    Mysql 系列文章主页 =============== 从 这篇 文章中,我们知道 Mysql 并发事务会引起更新丢失问题,解决办法是锁.所以本文将对锁(乐观锁.悲观锁)进行分析. 第一部分 悲观锁 ...

  2. mysql行锁、表锁。乐观锁,悲观锁

    锁定用于确保事务完整性和数据库一致性. 锁定可以防止用户读取其他用户正在更改的数据,并防止多个用户同时更改相同的数据. 如果不使用锁定,数据库中的数据可能在逻辑上变得不正确,而针对这些数据进行查询可能 ...

  3. Hibernate解决高并发问题之:悲观锁 VS 乐观锁

    高并发问题是程序设计所必须要解决的问题,解决此类问题最主要的途径就是对对程序进行加锁控制.hibernate对加锁机制同样做出了实现,常用加锁方式为悲观锁和乐观锁.悲观锁指的是对数据被外界(包括本系统 ...

  4. 025 hibernate悲观锁、乐观锁

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

  5. Hibernate的悲观锁和乐观锁

    前一篇博客我们从数据库角度分析,锁可以分为三种,分别为共享锁,独占锁和更新锁.我们从程序的角度来看锁可以分为两种类型,悲观锁和乐观锁,Hibernate提供对这两种锁 的支持,我们来了解一下Hiber ...

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

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

  7. Hibernate学习一:Hibernate注解CascadeType

    http://zy19982004.iteye.com/blog/1721846 ———————————————————————————————————————————————————————— Hi ...

  8. MySQL学习笔记(四)悲观锁与乐观锁

    恼骚 最近在搞并发的问题,订单的异步通知和主动查询会存在并发的问题,用到了Mysql数据库的 for update 锁 在TP5直接通过lock(true),用于数据库的锁机制 Db::name('p ...

  9. mysql中的锁机制之悲观锁和乐观锁

    1.悲观锁? 悲观锁顾名思义就是很悲观,悲观锁认为数据随时就有可能会被外界进行修改,所以悲观锁一上来就会把数据给加上锁.悲观锁一般都是依靠关系型数据库提供的锁机制,然而事实上关系型数据库中的行锁,表锁 ...

随机推荐

  1. erlang的斐波那契数列

    [递归和循环] 题目: 大家都知道斐波那契数列,现在要求输入一个整数N,请输出斐波那契数列的第N项,以及前N项. 如:N <=39 下面是斐波那契数列的实现: -module(feibo). - ...

  2. [转]postman 官方文档解说

    1. 安装 两种安装方式,我热衷于以chrome插件形式安装 Chrome插件 Mac App 2. 发送请求 Postman最基础的功能就是发送http请求,支持GET/PUT/POST/DELET ...

  3. Composer的Autoload源码实现1——启动与初始化

    前言 上一篇文章,我们讨论了 PHP 的自动加载原理.PHP 的命名空间.PHP 的 PSR0 与 PSR4 标准,有了这些知识,其实我们就可以按照 PSR4 标准写出可以自动加载的程序了.然而我们为 ...

  4. TP的分页加查询

    1.查询显示数据库的内容 控制器里的内容 public function shouye() { $n = M("car"); $arr = $n->select(); $th ...

  5. MATLAB循环结构:break+continue+嵌套

    break语句:终止当前循环,继续执行循环语句的下一语句: continue语句:跳过循环体的后面语句,开始下一个循环: 例:求[100,200]之间第一个能被21整除的整数 :200 %循环语句 ) ...

  6. wcf利用IDispatchMessageInspector实现接口监控日志记录和并发限流

    一般对于提供出来的接口,虽然知道在哪些业务场景下才会被调用,但是不知道什么时候被调用.调用的频率.接口性能,当出现问题的时候也不容易重现请求:为了追踪这些内容就需要把每次接口的调用信息给完整的记录下来 ...

  7. SuperAgent使用文档

    SuperAgent是一个轻量级.灵活的.易读的.低学习曲线的客户端请求代理模块,使用在NodeJS环境中.官方文档:http://visionmedia.github.io/superagent 简 ...

  8. [JavaScript]WebBrowser控件下IE版本的检测

    转载请注明原文地址:https://www.cnblogs.com/litou/p/10772272.htm 在客户端检查用户使用的浏览器类型和版本,都是根据navigator.userAgent属性 ...

  9. 被学长教会的高斯消元法Gauss

    昨天学长教了我高斯消元法. 这里用一个栗子来模拟一下Gauss的流程. 真的通俗易懂!这里是洛谷题目链接. 这就是例子 x-2y+3z= 4x-5y+6z= 7x-8y+10z= 先将它转化为矩阵 - ...

  10. JVM垃圾回收时的可触及性

    可触及的 1.从根节点可以触及到这个对象可复活的 1.一旦所有引用被释放,就是可复活状态 2.因为在finalize()中可能复活该对象不可触及的 1.在finalize()后,可能会进入不可触及状态 ...