在我们业务实现的过程中,往往会有这样的需求:保证数据访问的排他性,也就是我正在访问的数据,别人不能够访问,或者不能对我的数据进行操作.面对这样的需求,就需要通过一种机制来保证这些数据在一定的操作过程中不会被他人修改,这种机制就是我们今天要说的Locking 即"锁".由此我们可以得出一个小结论,锁主要是解决并发性问题.

Hibernate支持两种锁机制:"悲观锁"(Pessimistic
Locking )和"乐观锁"(Optimistic
Locking )

先来看悲观锁

通过悲观这两个字我们能够看出,它对数据被外界操作所采取的态度是悲观的,保守的.也就是在整个数据处理的过程中,,它都将数据处于锁定状态.悲观锁,通常是由数据库机制实现的,在整个过程中把数据锁住(查询时),只要事务不释放(提交/回滚)那么任何用户都不能查看或修改.需要等待资源释放.

接下来将通过一个简单查询语句来解释Hibernate是如何实现悲观锁.

  1. //查询用户为"jnqqls"的用户
  2. String hqlStr ="from User as user where user.name='Jnqqls'";
  3. Query query = session.createQuery(hqlStr);
  4. // 加锁
  5. query.setLockMode("user",LockMode.UPGRADE);
  6. // 执行查询,获取数据
  7. List userList = query.list();

通过查看运行时Hibernate的执行语句会发现,它是通过数据库的for update子句来实现了悲观锁的机制.

根据悲观锁的保守特点,在并发比较高的情况下不建议使用.特别是事务内的执行周期特别的长的情况下,其他请求资源都处于等待状态,导致数据库性能的大量开销.

接下来来看乐观锁

乐观锁(其实根本上不是锁,跟数据库没有关系.而是解决冲突的检测手段,机制是在数据库中加字段,例如增加一个版本号或者是时间戳).

Hibernate实现乐观锁机制的原理

大多数的使用是采用数据版本的方式(version)实现,一般在数据库中加入一个version字段在读取数据的时候将version读取出来,在保存数据的时候判断version的值是否小于数据库中的version值,如果小于不予更新,否则给予更新.

了解原理之后接下来我们将会通过代码来了解Hibernate是如何实现乐观锁.

第一步,在Hibernate配置文件中添加version字段,Hibernate会自动进行相关的锁处理.

  1. <?xml version="1.0"?>
  2. <!DOCTYPE hibernate-mapping PUBLIC
  3. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  5. <hibernate-mapping>
  6. <class name="com.tgb.hibernate.User" table="t_user" optimistic-lock="version">
  7. <id name="id">
  8. <generator class="assigned"/>
  9. </id>
  10. <version name="version"/>
  11. <property name="name"/>
  12. <property name="age"/>
  13. </class>
  14. </hibernate-mapping>

在此配置的过程中需要注意version的结点必须在id结点之后.此处version的作用注意是存放着用户的版本信息.

下面编写一段代码,将用户的年龄减少2岁.

  1. public void testLoad() {
  2. Session session = null;
  3. try {
  4. //一个获取session的工具.
  5. session = HibernateUtils.getSession();
  6. //开启事务
  7. session.beginTransaction();
  8. //加载用户id为1001
  9. User User = (User)session.load(User.class, "1001");
  10. //打印相关信息
  11. System.out.println("opt1-->Id=" + user.getId());
  12. System.out.println("opt1-->Name=" + user.getName());
  13. System.out.println("opt1-->Version=" + user.getVersion());
  14. System.out.println("opt1-->Age=" + user.getAge());
  15. user.setAge(user.getAge() - 2);
  16. //提交事务
  17. session.getTransaction().commit();
  18. }catch(Exception e) {
  19. e.printStackTrace();
  20. session.getTransaction().rollback();
  21. }finally {
  22. //关闭session
  23. HibernateUtils.closeSession(session);
  24. }
  25. }

通过操作可以发现,在每次更新User信息的时候,数据库中的version字段都在递增,如果我们在session提交之前开启另外一个session2对User年龄进行操作的话会出现错误提示.

org.hibernate.StaleObjectStateException:Row was updated ordeleted by another transaction(or
unsaved-value mapping was incorrect):…………..

我们可以进行异常捕获版本错误并对用户进行相应的提示,例如"数据已经被修改".

Hibernate 锁小结

悲观锁容易出现资源等待现象,因为对资源的完整占有.如果并发逻辑的时间过长的话则会导致系统其他并发逻辑的等待,会大大降低系统的并发性,并加大数据库的开销.

乐观锁因为采用版本机制,不会出现资源等待的现象,它会在提交数据的那一瞬间去判断版本的大小,如果出现并发修改的情况则会抛出异常错误,对于乐观锁而言,异常捕获显得尤为重要.

Hibernate 之 Locking的更多相关文章

  1. Hibernate 中的锁( locking )

    业务逻辑的实现过程中,往往需要保证数据访问的排他性.如在金融系统的日终结算处理中,我们希望针对某个 cut-off 时间点的数据进行处理,而不希望在结算进行过程中(可能是几秒种,也可能是几个小时),数 ...

  2. Hibernate 乐观锁(Optimistic Locking)

    1.hibernate基于数据版本(Version)记录机制实现.为数据增加一个版本标识,一般是通过为数据库表增加一个"version"字段来实现. 读取出数据时,将此版本号一同读 ...

  3. Hibernate 悲观锁(Pessimistic Locking)

    在日常开发中并发应该是比较常遇到的业务场景,Hibernate给我们提供了并发操作,接下来简单介绍一下Hibernate悲观控制. 悲观锁:用户其实并不需要花很多精力去担心锁定策略的问题,通常情况下, ...

  4. Hibernate中的锁机制

    锁机制:是数据库为了保证数据的一致性<一个事务的各种操作不相互影响>而使各种共享资源在被并发访问访问变得有序所设计的一种规则,用来保证在当前用户进行操作数据的时候其他的用户不能对同一数据进 ...

  5. Hibernate.lock()方法中各种锁的区别

    悲观锁 它指的是对数据被外界修改持保守态度.假定任何时刻存取数据时,都可能有另一个客户也正在存取同一笔数据,为了保持数据被操作的一致性,于是对数据采取了数据库层次的锁定状态,依靠数据库提供的锁机制来实 ...

  6. [转]Hibernate不能自动建表解决办法及Hibernate不同数据库的连接及SQL方言

    最近开始学Hibernate,看的是李刚的那本<轻量级java ee企业应用实战>.头一个hibernate程序,我原原本本的按照书上例子写下来,同时只是改动了些mysql的连接参数,并且 ...

  7. JavaPersistenceWithHibernate第二版笔记Getting started with ORM-001用JPA和Hibernate实现HellowWorld(JTA、Bitronix)

    一.结构 二.model层 1. package org.jpwh.model.helloworld; import javax.persistence.Entity; import javax.pe ...

  8. hibernate注解(转)

    一.实体Bean 每个持久化POJO类都是一个实体Bean, 通过在类的定义中使用 @Entity 注解来进行声明. 声明实体Bean @Entity public class Flight impl ...

  9. HIbernate学习笔记(八) hibernate缓存机制

    hibernate缓存 一. Session级缓存(一级缓存) 一级缓存很短和session的生命周期一致,因此也叫session级缓存或事务级缓存 hibernate一级缓存 那些方法支持一级缓存: ...

随机推荐

  1. vue App.vue router 过渡效果, keep-alive 结合使用示例

    1, router.js配置 每个路由的index值 2, router.js配置 每个路由的keepAlive值 app.vue 代码 <template> <div id=&qu ...

  2. python基础知识03-格式化输出和深浅复制

    VIM中HJKL可以上下左右移动光标. 格式化输出和深浅复制 1.字符串的拼接和格式化 sudo pip3 install ipython 安装 ipython 进入 字符串相加 str1 + str ...

  3. 一直被用错的6种SQL 错误用法

    一直被用错的6种SQL 错误用法 1.LIMIT 语句 2.隐式转换 3.关联更新.删除 4.EXISTS语句 5.条件下推 6.提前缩小范围 sql语句的执行顺序: FROM ON JOIN WHE ...

  4. 基于flask的网页聊天室(三)

    基于flask的网页聊天室(三) 前言 继续上一次的内容,今天完成了csrf防御的添加,用户头像的存储以及用户的登录状态 具体内容 首先是添加csrf的防御,为整个app添加防御: from flas ...

  5. python 文件操作(二) 替换性修改文件内容

    正常情况我们想要仅对文件某一行的内容进行修改,而不改变其他内容,在原文件的基础上不能修改,因为当我们对原文件进行写操作时,如果原文件里面有内容,就会清空,在这种情况下,只能对文件进行替换性修改:即重新 ...

  6. python中的多任务

    多任务 什么是任务 一个电脑运行这的软件 什么是多任务 电脑同时运行着的多个软件 多任务原理 时间片的轮转 并行与并发 并发:假的多任务,多个任务共用一个核 并行:正的多任务,一个核处理一个程序 生理 ...

  7. Java多线程入门Ⅱ

    线程的让步 线程让出自己占用的CPU资源 线程让出资源,不指定让给谁 线程让出资源,指定让给谁 方法1: public static void yield(); 线程实现交替打印 import jav ...

  8. POJ 1144 Network (求割点)

    题意: 给定一幅无向图, 求出图的割点. 割点模板:http://www.cnblogs.com/Jadon97/p/8328750.html 分析: 输入有点麻烦, 用stringsteam 会比较 ...

  9. mysql 常用命令(二)

    1.创建数据库,并制定默认的字符集是utf8. CREATE DATABASE IF NOT EXISTS yourdbname DEFAULT CHARSET utf8 COLLATE utf8_g ...

  10. Android Ubuntu 12.04 源码环境搭建

    $ sudo apt-get install git gnupg flex bison gperf build-essential \ zip curl libc6-dev libncurses5-d ...