hibernate---->悲观锁和乐观锁
一、悲观锁
悲观锁的实现,通常依赖于数据库机制,在整个过程中将数据锁定,其它任何用户都不能读取或修改
悲观锁的实现:
显式的用户指定"可以通过以下几种方式之一来表示:
-
调用 Session.load()的时候指定锁定模式(LockMode)。
-
调用Session.lock()。
-
调用Query.setLockMode()。
package com.wsz.test;
import junit.framework.TestCase;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.wsz.entity.HibernateUtils;
import com.wsz.entity.Products;
public class Test extends TestCase {
public void testSave() {
Session session = null;
Transaction tx = null;
Products products = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
products=new Products();
products.setName("脑白金");
products.setTotalnumber(1000);
session.save(products);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
public void test1() {
Products products = new Products();
Session session = HibernateUtils.getSession();
session.beginTransaction();
//悲观锁的实现
products = (Products) session.load(products.getClass(), 1,LockMode.UPGRADE);
System.out.print(products.getName());
System.out.println(products.getTotalnumber());
products.setTotalnumber(products.getTotalnumber()-200);
session.getTransaction().commit();
}
public void test2() {
Products products = new Products();
Session session = HibernateUtils.getSession();
session.beginTransaction();
products = (Products) session.load(products.getClass(), 1,LockMode.UPGRADE);
System.out.print(products.getName());
System.out.println(products.getTotalnumber());
products.setTotalnumber(products.getTotalnumber()-200);
session.getTransaction().commit();
}
}
使用悲观锁,lazy属性失效,立即发出sql。
二、乐观锁
大多数基于数据版本记录机制(version)实现,一般是在数据库表中加入一个version字段,读取数据时将版本号一同读出,之后更新数据时版本号加一,如果提交数据时版本号小于或等于数据表中的版本号,则认为数据是过期的,否则给予更新。
Products.hbm.xml
<hibernate-mapping> <class name="com.wsz.entity.Products" table="t_products" optimistic-lock="version"> <id name="id"> <generator class="native" /> </id> <version name="version"/> <property name="name" /> <property name="totalnumber" /> </class> </hibernate-mapping>
数据库表多了一个version字段

开始version=0

如果更新后 version=1,由数据库自动更新。

Products.java
package com.wsz.entity;
public class Products {
private int id;
private String name;
private int totalnumber;
private int version;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getTotalnumber() {
return totalnumber;
}
public void setTotalnumber(int totalnumber) {
this.totalnumber = totalnumber;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
}
Test.java
package com.wsz.test;
import junit.framework.TestCase;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.wsz.entity.HibernateUtils;
import com.wsz.entity.Products;
public class Test extends TestCase {
public void testSave() {
Session session = null;
Transaction tx = null;
Products products = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
products=new Products();
products.setName("naobaijin");
products.setTotalnumber(1000);
session.save(products);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
public void test1() {
Products products = new Products();
Session session = HibernateUtils.getSession();
session.beginTransaction();
//悲观锁的实现
products = (Products) session.load(products.getClass(), 1);
System.out.print(products.getName());
System.out.println(products.getTotalnumber());
products.setTotalnumber(products.getTotalnumber()-200);
session.getTransaction().commit();
}
public void test2() {
Products products = new Products();
Session session = HibernateUtils.getSession();
session.beginTransaction();
products = (Products) session.load(products.getClass(), 1);
System.out.print(products.getName());
System.out.println(products.getTotalnumber());
products.setTotalnumber(products.getTotalnumber()-200);
session.getTransaction().commit();
}
}
使用悲观锁,lazy不会失效,不会立即发出sql
更新时发出的sql语句Hibernate: update t_products set version=?, name=?, totalnumber=? where id=? and version=?,
如果test1更新了,在commit设置断点,没有提交,test2更新了。此时test1往下运行,当前的version 小于数据库的version ,会生成如下的异常。
10:48:59,260 ERROR AbstractFlushingEventListener:301 - Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.wsz.entity.Products#1]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1699)

浙公网安备 33010602011771号