在我们业务实现的过程中,往往会有这样的需求:保证数据访问的排他性,也就是我正在访问的数据,别人不能够访问,或者不能对我的数据进行操作.面对这样的需求,就需要通过一种机制来保证这些数据在一定的操作过程中不会被他人修改,这种机制就是我们今天要说的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. Specified VM install not found: type Standard VM, name JDK1.8

    真正的问题解决方法在这里:在项目中,右键点击ant文件,选择Run As -- External Tools Configuration,在这个页面的顶端就会看到有红叉叉的报错,报错信息就是Speci ...

  2. Mybatis判断int类型是否为空

     Mybatis判断int是否为空只要!=null就行了  

  3. mysql汉字转拼音函数

    -- 创建汉字拼音对照临时表 CREATE TABLE IF NOT EXISTS `t_base_pinyin` ( `pin_yin_` ) CHARACTER SET gbk NOT NULL, ...

  4. hust训练赛20160330--B - 又见LKity

    Problem 2122 又见LKity Time Limit: 1000 mSec Memory Limit : 32768 KB  Problem Description 嗨!大家好,在Templ ...

  5. 让你的 CDN 费用省 50% 以上!图片瘦身的正确姿势

    七牛云新推出的图片瘦身功能是做什么的? 打开七牛云的「数据处理」中的「图片瘦身」功能,在图片受到访问时,能够实时对图片进行瘦身,在保证分辨率和画质不变的情况下,可以将图片最高缩小 80%.当「图片瘦身 ...

  6. 洛谷P1504 积木城堡

    题目描述 XC的儿子小XC最喜欢玩的游戏用积木垒漂亮的城堡.城堡是用一些立方体的积木垒成的,城堡的每一层是一块积木.小XC是一个比他爸爸XC还聪明的孩子,他发现垒城堡的时候,如果下面的积木比上面的积木 ...

  7. 兴奋剂检查(vijos 1426)

    背景 北京奥运会开幕了,这是中国人的骄傲和自豪,中国健儿在运动场上已经创造了一个又一个辉煌,super pig也不例外……………… 描述 虽然兴奋剂是奥运会及其他重要比赛的禁药,是禁止服用的.但是运动 ...

  8. 洛谷P3406 海底高铁

    题目背景 大东亚海底隧道连接着厦门.新北.博艾.那霸.鹿儿岛等城市,横穿东海,耗资1000亿博艾元,历时15年,于公元2058年建成.凭借该隧道,从厦门可以乘坐火车直达台湾.博艾和日本,全程只需要4个 ...

  9. hdu4405:Aeroplane chess

    题目大意:有编号为0-n的格子,从0开始,扔骰子扔到几就走几格.有m个瞬移点,每个点可以从格x直接飞到格y,若瞬移到另一个瞬移点可以继续瞬移.求到达格n的期望扔骰子次数. 题解:期望DP入门好题.网上 ...

  10. CF671D:Roads in Yusland

    n<=300000个点的树,给m<=300000条带权路径(ui,vi,保证vi是ui的祖先)求覆盖整棵树每条边的最小权和. 好题好姿势!直观的看到可以树形DP,f[i]表示把点i包括它爸 ...