025 hibernate悲观锁、乐观锁
Hibernate谈到悲观锁、乐观锁,就要谈到数据库的并发问题,数据库的隔离级别越高它的并发性就越差
并发性:当前系统进行了序列化后,当前读取数据后,别人查询不了,看不了。称为并发性不好
数据库隔离级别:见前面章级
025-1悲观锁:
悲观锁:具有排他性(我锁住当前数据后,别人看到不此数据)
悲观锁一般由数据机制来做到的。
悲观锁的实现
通常依赖于数据库机制,在整修过程中将数据锁定,其它任何用户都不能读取或修改(如:必需我修改完之后,别人才可以修改)
悲观锁的适用场景:
悲观锁一般适合短事务比较多(如某一数据取出后加1,立即释放)
长事务占有时间(如果占有1个小时,那么这个1小时别人就不可以使用这些数据),不常用。
实例:
实体类:
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; } } |
映射文件:
<hibernate-mapping> <class name="com.wjt276.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 arg0, 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(); |
执行输出SQL语句:
Hibernate: select inventory0_.itemNo as itemNo0_0_, inventory0_.itemName as itemName0_0_, inventory0_.quantity as quantity0_0_ from t_inventory inventory0_ where inventory0_.itemNo=? for update //在select语句中加入for update进行使用悲观锁。 脑白金 Hibernate: update t_inventory set itemName=?, quantity=? where itemNo=? 注:只有用户释放锁后,别的用户才可以读取 |
注:如果使用悲观锁,那么lazy(悚加载无效)
025-2乐观锁:
乐观锁:不是锁,是一种冲突检测机制。
乐观锁的并发性较好,因为我改的时候,别人随边修改。
乐观锁的实现方式:常用的是版本的方式(每个数据表中有一个版本字段version,某一个用户更新数据后,版本号+1,另一个用户修改后再+1,当用户更新发现数据库当前版本号与读取数据时版本号不一致(等于小于数据库当前版本号),则更新不了。
Hibernate使用乐观锁需要在映射文件中配置项才可生效。
实体类:
public class Inventory { private int itemNo; private String itemName; private int quantity; private int version;//Hibernate用户实现版本方式乐观锁,但需要在映射文件中配置 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; } public int getVersion() { return version; } public void setVersion(int version) { this.version = version; } } |
映射文件
<hibernate-mapping> <!-- 映射实体类时,需要加入一个开启乐观锁的属性 optimistic-lock="version" 共有好几种方式: - none - version - dirty - all 同时需要在主键映射后面映射版本号字段 --> <class name="com.wjt276.hibernate.Inventory" table="t_inventory" optimistic-lock="version"> <id name="itemNo"> <generator class="native"/> </id> <version name="version"/><!—必需配置在主键映射后面 --> <property name="itemName"/> <property name="quantity"/> </class> </hibernate-mapping> |
导出输出SQL语句:
create table t_inventory (itemNo integer not null auto_increment, version integer not null, itemName varchar(255), quantity integer, primary key (itemNo))
|
注:添加的版本字段version,还是我们来维护的,是由hibernate来维护的。
乐观锁在存储数据时不用关心。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。