Hibernate中乐观锁和悲观锁。

在hibernate事务处理中造成的写问题(丢失更新的问题:更新一定是查询最新的结果),之前博客简单描述了一下解决方法,这篇博客,来详细讲解一下如何用乐观锁悲观锁解决写问题。

下面我们通过例子来理解:

在事务操作中,最经典的就是转账案例,

如图所示:

AB两个用户同时操作数据库,A用户在原余额上添加了10块钱,所以是110元,但是B用户添加了30元,却变成了140元,这就造成了并发操作的时候,引发的丢失更新。

用代码来看:

public void test1(){
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();

Customer customer =(Customer) session.get(Customer.class, 6);
customer.setMoney(customer.getMoney()+10);

transaction.commit();
HibernateUtils.closeSession(session);
}
public void test2(){
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();

Customer customer =(Customer) session.get(Customer.class, 6);
customer.setMoney(customer.getMoney()+30);

transaction.commit();
HibernateUtils.closeSession(session);
}

同时运行两段代码,数据库中:

解决方法有两种

乐观锁和悲观锁

乐观锁(s锁,share锁,共享锁):

                在Customer.hbm.xml配置文件中配置一个<version>标签,并且要在Customer.java类中也要添加Integet类型的version字段(字段名称可以随便取)

位置写在id标签的下面:

配置好以后,启动运行,数据库中:

这个时候在运行上面test1和test2的代码块:

同时运行,test1代码先执行完后,数据库中:

test2代码执行完后:会报错

这个时候我们设置的乐观锁就拦截成功了。

乐观锁原理:

                事务1和事务2同时运行,事务1和事务2查询到的数据库version都为0,然后事务1先执行添加操作,version会变成1,sql语句为:

                这时候事务1还没有执行完(还没有commit),然后这时候事务2进行添加操作,会先查询最新出最新的结果,执行sql的时候,会发现version不相等,因为之前事务2查到的version为0,而现在变成了1,所以执行失败,会报错。

下面来看悲观锁。首先,hibernate不建议使用悲观锁.

悲观锁:

public void test1(){
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();

Customer customer =(Customer) session.get(Customer.class, 6, LockMode.UPGRADE);//在这加了一个LockMode.UPGRADE
customer.setMoney(customer.getMoney()+10);

transaction.commit();
HibernateUtils.closeSession(session);
}

这时候执行后,sql语句:

缺点是:当有10个事务同时执行的话,要先阻塞等待第一个事务执行完之后,才会继续执行接下来的事务。

猜你喜欢

转载自blog.csdn.net/weixin_42719412/article/details/83184458