hibernate悲观锁和乐观锁
1.悲观锁
具有排它性(我锁住当前数据后,比人看不到此数据),悲观锁一般是由数据库机制来做到的
悲观锁的实现:
通常依赖于数据库机制,在整修过程中将数据库锁定,其它任何用户都不能读取或修改悲观锁的适用场景:
悲观锁一般适合短事物比较多(如某一个数据取出后加1,立即释放)
总共有quantity=1000个,用户1,用户2同时读取到数据,但是用户2先-200,这时数据库里的是800,现在用户1也开始-200,可以用户1刚才读取到的数据是1000,现在用户用刚一开始读取的数据1000-200,而用户1在更新时数据库里的数据是800,按理说用户1应该是800-200=600,这样就造成更新丢失。这种情况下可采用两种方式解决:悲观锁、乐观锁。
悲观锁:用户1读取数据后,用锁将其读取的数据锁上,这时用户2是读取不到数据的,只有用户1释放锁后用户2才可以读取,同样用户2读取数据的数据也锁上,这样就可以解决更新丢失了。
Entity
public class Inventory {
private int itemNo;
private String itemName;
private int quantity;
public int getItemNo() {
return itemNo;
}
public void setItemNo(int itemNo) {
this.itemNo = itemNo;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
hiberante-mapping file:
<hibernate-mapping>
<class name="com.cn.hibernate.Inventory" table="t_inventory">
<id name="itemNo">
<generator class="native"/>
</id>
<property name="itemName"/>
<property name="quantity"/>
</class>
</hibernate-mapping>
悲观锁的使用:
如果要使用悲观锁,肯定在加载数据时就要锁住,通常采用for update语句
hibernate使用load进行悲观锁加载
Session.load(Class arg(),Serializable arg1,LockMode arg2)throws HibernateException
LockMode:悲观锁模式(一般使用LockMode.UPGRADE)
session = HibernateUtils.getSession();
tx = session.beginTransaction();
Inventory inv = (Inventory)session.load(Inventory.class, 1, LockMode.UPGRADE);
System.out.println(inv.getItemName());
inv.setQuantity(inv.getQuantity()-200);
session.update(inv);
tx.commit();