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

    1.Eclipse中 NEW ->OTHER->Maven->maven project 2.选择项目路径 3.选择项目类型->next->输入groupid和artif ...

  2. 剑指Offer(书):替换空格

    题目:请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 分析:通常来说,这样的题有两种方式 ...

  3. POJ 1161 Walls(Floyd , 建图)

    题意: 给定n个城市, 然后城市之间会有长城相连, 长城之间会围成M个区域, 有L个vip(每个vip会处于一个城市里)要找一个区域聚会, 问一共最少跨越多少个长城. 分析: 其实这题难就难在建图, ...

  4. 如何在小程序自定义组件和动态传入数据小demo

    在开发过程中,我们会将页面常用功能抽象为一个组件,这样既方便又可以避免代码冗余.小程序中也提供了自定义组件,了解Vue的伙伴们会发现其实和Vue的组件化很相似.这里用返回顶部功能来说说如何自定义组件, ...

  5. python基础知识--条件判断和循环

    一.输入输出 python怎么来接收用户输入呢,使用input函数,python2中使用raw_input,接收的是一个字符串,输出呢,第一个程序已经写的使用print,代码入下: 1 name=in ...

  6. Java并发编程:自己动手写一把可重入锁

    关于线程安全的例子,我前面的文章Java并发编程:线程安全和ThreadLocal里面提到了,简而言之就是多个线程在同时访问或修改公共资源的时候,由于不同线程抢占公共资源而导致的结果不确定性,就是在并 ...

  7. POJ 1276 Cash Machine 【DP】

    多重背包的模型,但一开始直接将N个物品一个一个拆,拆成01背包竟然T了!!好吧OI过后多久没看过背包问题了,翻出背包九讲看下才发现还有二进制优化一说........就是将n个物品拆成系数:1,2,4, ...

  8. POJ 2420 A Star not a Tree?【爬山法】

    题目大意:在二维平面上找出一个点,使它到所有给定点的距离和最小,距离定义为欧氏距离,求这个最小的距离和是多少(结果需要四舍五入)? 思路:如果不能加点,问所有点距离和的最小值那就是经典的MST,如果只 ...

  9. 洛谷P1504 积木城堡

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

  10. [NOIP2002] 提高组 洛谷P1034 矩形覆盖

    题目描述 在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示.例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一. 这 ...