Hibernate悲观锁和乐观锁详解
来源:互联网 发布:datax导入数据到hive 编辑:程序博客网 时间:2024/06/12 19:44
业务实现过程中,难免需要保证数据访问的排他性。如金融系统的日终结算中,我们会针对某个截止点的数据进行处理,在此同时,不希望在结算的这段时间里(几秒钟或者几个钟头),数据再有变动,不然我们的统计也无效了。这种时候,我们为了保证某些数据在某个操作中不被外界修改,就引入了我们hibernate的锁机制,一旦我们给目标上锁,其他程序则不能去修改。hibernate中锁是两种,悲观和乐观锁。
1、悲观锁
悲观锁:它指的是对数据被外界(包括本系统当前的其他事物,以及来自外部系统的事务处理)修改,保持保守态度,因此整个处理过程中,数据一致处于被锁定的状态,悲观锁的实现,往往依靠数据提供的锁机制(也只有数据库层提供的锁机制,才能真正保证排他性,否则本系统中实现加锁机制,并不能一定保证外部系统不会修改数据)。
依赖数据库实现的悲观锁的调用:
select * from account where name="Erica" for update
通过for update子句,sql锁定了account中,所以符合名字等于erica的记录。即在本次事物提交之前(事物提交时会释放事物过程中的锁),外界无法修改这些记录。hibernate的悲观锁,也是基于数据库的锁机制实现的,下面代码实现了对查询记录的加锁:
- String hqlStr="from User user where uesr.name='Erica' ";
- Query query=session.createQuery(hqlStr);
- query.setLockMode("user",LockMode.UPGRADE); //加锁
- List userList=query.list(); //获得数据
Hibernate的加锁模式则分为:
- LockMode.NONE:无锁
- LockMode.WRITE:hibernate在insert和update记录的时候会自动获取
- LockMode.READ: hibernate在读取数据的时候会自动获取。
- LockMode.UPGRADE:利用数据的for update子句加锁,
- LockMode.UPGRADE_NOWAIT: oracle特定的实现,利用oracle的for update nowait子句实现加锁。
乐观锁,则采取更加宽松的机制加锁。悲观的大都靠数据库的for update实现,在保证了独占性外,性能会相对消耗较大。对于长事物而言,基本无法承受额样的开销。而乐观锁则是通过给数据库增加一个version字段,通过比较版本信息,从而实现加锁机制。
数据库的accout表中,记录着张三的账户上有100块钱,此时银行还未上班,张三也未存取或转账,这时,乐观锁情况下,这个100块是version=1的,而然在上班之后,银行操作员a,将账户查了出来,在进行扣除,他想着要扣多少钱才好,于是他边喝咖啡边想,这时候,操作员b也来了,查到了张三的账户也想扣他的钱,这时a想好了,先行扣了张三的50块,即100-50,然后愉快的提交了,此时张三账户的version字段被+1,成为version=2了。后来b了想好了,扣了它20块,即100-20,他也想提交,但是突然报出提示,不能提交,缘故是提交的版本必须大于记录的版本才能执行,哦,他这才知道原来张三的账户已经被修改过了,所以才被驳回。
从上面的例子可以看出,乐观锁避免了长事务中的数据加锁的开销,操作员a和b在操作时,都未加锁,从而大大提升了大并发量的系统的整体的性能表现。而hibernate在其数据访问引擎中内置了对乐观锁的实现。如果不考虑外部系统对数据库的更新操作,利用hibernate提供的透明化的乐观所机制将大大提升生产力。
给对象乐观锁的办法,即添加optimistic-lock属性:
- <hibernate-mapping>
- <class name="com.entity.Uesr" table="User" dynamic-update="true " dynamic-insert="true" optimistic-lock="vsersion">
- <version column="version" name="version" type="java.lang.Integer"/>
- ......
- </class>
- </hibernate-mapping>
代码如下:
- Criteria ct=session.createCriteria(User.class);
- ct.add(Expression.eq("name","Erica"));
- List userList=ct.list();
- User user=(User)userList.get(0);
- Transaction tx=session.beginTransaction();
- user.setUserType(1)'; //更新UserType字段为1
- tx.commit();
- Hibernate悲观锁和乐观锁详解
- Hibernate中悲观锁和乐观锁详解
- hibernate悲观锁与乐观锁详解
- hibernate中的悲观锁和乐观锁
- hibernate中的悲观锁和乐观锁
- Hibernate 中悲观锁和乐观锁
- hibernate悲观锁和乐观锁
- Hibernate乐观锁和悲观锁
- Hibernate的悲观锁和乐观锁
- hibernate的 悲观锁和乐观锁
- Hibernate 悲观锁和乐观锁
- Hibernate中悲观锁和乐观锁
- Hibernate乐观锁和悲观锁
- Hibernate中悲观锁和乐观锁
- Hibernate中悲观锁和乐观锁
- Hibernate中悲观锁和乐观锁
- hibernate---->悲观锁和乐观锁
- Hibernate:悲观锁和乐观锁
- 关于快速排序的见解(分治法)
- sp与isag的开发包短信彩信
- Ruby之self详解(一)详细剖析
- main函数的参数(argc和argv)
- sp与ISMP接口开发包1短信彩信
- Hibernate悲观锁和乐观锁详解
- PHP session原理总结
- POJ Problem Id1006 :Biorhythms ACM 编程练习
- 下拉菜单
- poj 1321棋盘问题
- 5311 Exponentiation
- 深入体验JavaWeb开发内幕——关于JSP的映射、JSP错误查找以及JavaBean与JSP相关知识介绍
- const int *a, int const *a,int * const a,区别,指针数组,数组指针,声明与定义
- 十进制转化为七进制