您的位置:首页 > 其它

笔记---Hibernate并发(悲观锁和乐观锁)

2016-08-08 16:15 225 查看
如下,有两个测试方法,test01让其执行update去修改学生id值为1的学生的name为“科比”,test02让其执行update去修改同样学生id值为1的学生的sex为“女”。

默认数据库中id为的学生信息:



@Test
public void test01(){
Session session = null ;
try {
session = HibernateUtil.openSession() ;
session.beginTransaction();

Student student = (Student) session.load(Student.class, 1);
student.setName("科比");

session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
if(session!=null) session.getTransaction().rollback();
} finally {
HibernateUtil.closeSession(session);
}
}


@Test
public void test02(){
Session session = null ;
try {
session = HibernateUtil.openSession() ;
session.beginTransaction();

Student student = (Student) session.load(Student.class, 1);
student.setSex("女");

session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
if(session!=null) session.getTransaction().rollback();
} finally {
HibernateUtil.closeSession(session);
}
}


同时开始执行test01跟test02,当test01执行完事务提交之后,数据库之后的结果如下:



然后将test01的断点走完,然后继续执行test02的事务提交,执行完成后结果如下:



这就是hibernate 同时执行造成的“更新丢失”的问题,第一次更新的时候已经把id为1的学生查出来了,更新成功之后,

数据库也成功更新了;然而第二次更新的时候跟第一次更新的时候是同时进行的,也就是说两个方法开始做更新操作的时候都是取得同样的id为1的学生的信息

方法一执行成功了,完成了更新这没有问题,然后方法二更新的时候,由于数据库中的name已经被方法1更新掉了,相对于方法二来说,此时,

他的对象的name跟sex都不一致,所以方法二在做更新的时候同事修改了name跟sex,由于name是取得初始的数据,所以最后更新完成之后的结果如上图所示。

解决方案一:悲观锁

test01跟test02中代码做如下修改,load时加一个参数。

Student student = (Student) session.load(Student.class, 1, LockOptions.UPGRADE);


此时再测试的 时候,当test01跟test02方法同时开始执行的时候,相对于test02来说test01是第一个读取student对象的,而test02是第二个读取student对象的,当testf01和test02同时做修改操作的时候,当test02执行提交的时候,此时会开启悲观锁,运行线程停在当前要执行提交的位置,只有当test01读取的student读取完毕,完成提交之后才能继续执行test02

当然最后的执行结果是,name跟sex都是修改了。



解决方案二:乐观锁

乐观锁是在数据库中增加一个version的字段来实现的,每一次修改都会这个字段的值加1,在读取的时候根据version这个字段的版本来判断。

同样是用test01和test02的例子,在t_student数据库表中增加一个version的字段,在student.hbm.xml文件中紧跟id后面添加

<version name="version" />


在student对应的实体类中也增加对应的属性,以及setter,getter方法。然后再执行的过程中会发现对应的数据库表已经添加了默认的“version”字段,初始值为0,当某个对象中无论那个属性对应的字段做了修改,他的 version的值都会加一。此时如果两个方法并发操作去做修改操作的话,在执行版本低的方法时会抛出版本不一致的异常信息来,



解决的办法就是再更新一次就成功了

小结:

悲观锁:比作人的话,说这人心态是悲观的,自己在获取数据的时候总是认为别人会在自己获取数据的同时去修改数据,所 以在自己获取数据的时候对数据上锁,这样别人获取数据的时候是被锁的状态,只有当第一个获取数据的人操作完成的时候,其他人的操作才能继续进行。

乐观锁:比作人的话,说这人心态是乐观的,自己在获取数据的时候不担心别人会在自己获取数据的同时去修改数据,而是在自己要提交或者说更新数据到数据库

操作的时候会自己当前提交的版本号跟当前数据库中的版本号做判断,如果自己提交的版本号大于数据库中的版本号,则说明自己要提交的版本是最新版本,可以正常操作,如果自己提交的版本号小于数据库中的版本号,则说明自己提交的数据对应的版本已经过时了,提交会抛出异常,解决办法就是再重新提交一次,因为重新提交的时候会重新获取最新的版本号。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐