悲观锁的实现 :悲观锁依赖于数据库机制,在整个过程中将数据锁定,其他任何人都不能读取或修改
乐观锁:
大多数基于数据版本记录机制(Version)的实现,一般是在数据库表中加入一个version字段,还有时间戳等机制
读取数据时将版本一同读出,之后更新数据时版本号加1,如果提交数据时版本号小于或者等于数据库中的版本号
则认为数据是过期的否则给予更新
下面我们举例说明:
- package com.june.hibernate;
-
- public class Inventory {
- public Integer itemNo;
- public String itemName;
- public int quantity;
- ........
- }
package com.june.hibernate;
public class Inventory {
public Integer itemNo; //物料编号
public String itemName;//物料名称
public int quantity; //数量
........//get/set方法省略
}
当我们采用乐观锁时映射文件:
- <class name="com.june.hibernate.Inventory" table="t_inventory">
- <id name="itemNo">
- <generator class="native" ></generator>
- </id>
- <property name="itemName" length="32" />
- <property name="quantity"></property>
- </class>
<class name="com.june.hibernate.Inventory" table="t_inventory">
<id name="itemNo">
<generator class="native" ></generator>
</id>
<property name="itemName" length="32" />
<property name="quantity"></property>
</class>
我们运行如下2个单元测试:
testLoad1();
- public void testLoad1(){
- Session session=null;
- Transaction tx=null;
- try{
- session=HibernateUtil.getSession();
- tx=session.beginTransaction();
- Inventory inventory=(Inventory)session.load(Inventory.class,2,LockMode.UPGRADE);
- System.out.println("@inventory.id="+inventory.getItemNo());
- System.out.println("@inventory.itemName="+inventory.getItemName());
- System.out.println("@inventory.quantity="+inventory.getQuantity());
-
- System.out.println("@提货减去200...............");
- inventory.setQuantity(inventory.getQuantity()-200);
-
- tx.commit();
- }catch(Exception e){
- e.printStackTrace();
- tx.rollback();
- }finally{
- HibernateUtil.colseSession(session);
- }
-
- }
public void testLoad1(){
Session session=null;
Transaction tx=null;
try{
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Inventory inventory=(Inventory)session.load(Inventory.class,2,LockMode.UPGRADE);
System.out.println("@inventory.id="+inventory.getItemNo());
System.out.println("@inventory.itemName="+inventory.getItemName());
System.out.println("@inventory.quantity="+inventory.getQuantity());
System.out.println("@提货减去200...............");
inventory.setQuantity(inventory.getQuantity()-200);//(1)
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
}
testLoad2()
- public void testLoad2(){
- Session session=null;
- Transaction tx=null;
- try{
- session=HibernateUtil.getSession();
- tx=session.beginTransaction();
- Inventory inventory=(Inventory)session.load(Inventory.class,2,LockMode.UPGRADE);
- System.out.println("#inventory.id="+inventory.getItemNo());
- System.out.println("#inventory.itemName="+inventory.getItemName());
- System.out.println("#inventory.quantity="+inventory.getQuantity());
-
- System.out.println("#提货减去200...............");
- inventory.setQuantity(inventory.getQuantity()-200);
-
- tx.commit();
- }catch(Exception e){
- e.printStackTrace();
- tx.rollback();
- }finally{
- HibernateUtil.colseSession(session);
- }
-
- }
- }
public void testLoad2(){
Session session=null;
Transaction tx=null;
try{
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Inventory inventory=(Inventory)session.load(Inventory.class,2,LockMode.UPGRADE);
System.out.println("#inventory.id="+inventory.getItemNo());
System.out.println("#inventory.itemName="+inventory.getItemName());
System.out.println("#inventory.quantity="+inventory.getQuantity());
System.out.println("#提货减去200...............");
inventory.setQuantity(inventory.getQuantity()-200);
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
}
}
我们用debug方法testLoad1()的方法执行时 我们让方法执行到(1)(断点一定要设置它的前面)处停止下来,我们在来运行testLoad2() 我们会发现 在加载了对象之后,也就是
执行了查询sql语句之后会停下来;当我们运行完testLoad1()之后,也就是提交了事务,解除了悲观锁之后testLoad2()才能继续运行。
乐观锁:
我们来用数据版本来实现乐观锁
我们来看Inventory的生命
- package com.june.hibernate;
-
- public class Inventory {
- public Integer itemNo;
- public String itemName;
- public int quantity;
- public Integer version;
- ..............
- }
package com.june.hibernate;
public class Inventory {
public Integer itemNo;
public String itemName;
public int quantity;
public Integer version;
..............
}
映射文件
- <class name="com.june.hibernate.Inventory"table="t_inventory" optimistic-lock="version">
- <id name="itemNo">
- <generator class="native" ></generator>
- </id>
-
- <version name="version"></version>
- <property name="itemName" length="32" />
- <property name="quantity"></property>
- </class>
<class name="com.june.hibernate.Inventory"table="t_inventory" optimistic-lock="version">
<id name="itemNo">
<generator class="native" ></generator>
</id>
<!-- version一定要紧挨着Id-->
<version name="version"></version>
<property name="itemName" length="32" />
<property name="quantity"></property>
</class>
生成的数据库表中
我们在来运行如下的单元测试:
-
-
-
- public void testLoad1(){
- Session session=null;
- Transaction tx=null;
- try{
- session=HibernateUtil.getSession();
- tx=session.beginTransaction();
- Inventory inventory=(Inventory)session.load(Inventory.class,1);
- System.out.println("@inventory.id="+inventory.getItemNo());
- System.out.println("@inventory.itemName="+inventory.getItemName());
- System.out.println("@inventory.quantity="+inventory.getQuantity());
- System.out.println("@inventroy.version="+inventory.getVersion());
- System.out.println("@提货减去200...............");
- inventory.setQuantity(inventory.getQuantity()-200);
-
- tx.commit();
- }catch(Exception e){
- e.printStackTrace();
- tx.rollback();
- }finally{
- HibernateUtil.colseSession(session);
- }
-
- }
-
-
-
- public void testLoad2(){
- Session session=null;
- Transaction tx=null;
- try{
- session=HibernateUtil.getSession();
- tx=session.beginTransaction();
- Inventory inventory=(Inventory)session.load(Inventory.class,1);
- System.out.println("#inventory.id="+inventory.getItemNo());
- System.out.println("#inventory.itemName="+inventory.getItemName());
- System.out.println("#inventory.quantity="+inventory.getQuantity());
-
- System.out.println("#提货减去200...............");
- inventory.setQuantity(inventory.getQuantity()-200);
-
- tx.commit();
- }catch(Exception e){
- e.printStackTrace();
- tx.rollback();
- }finally{
- HibernateUtil.colseSession(session);
- }
-
- }
/**
* testLoad2()
*/
public void testLoad1(){
Session session=null;
Transaction tx=null;
try{
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Inventory inventory=(Inventory)session.load(Inventory.class,1);
System.out.println("@inventory.id="+inventory.getItemNo());
System.out.println("@inventory.itemName="+inventory.getItemName());
System.out.println("@inventory.quantity="+inventory.getQuantity());
System.out.println("@inventroy.version="+inventory.getVersion());
System.out.println("@提货减去200...............");
inventory.setQuantity(inventory.getQuantity()-200);
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
}
/**
* testLoad2()
*/
public void testLoad2(){
Session session=null;
Transaction tx=null;
try{
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Inventory inventory=(Inventory)session.load(Inventory.class,1);
System.out.println("#inventory.id="+inventory.getItemNo());
System.out.println("#inventory.itemName="+inventory.getItemName());
System.out.println("#inventory.quantity="+inventory.getQuantity());
System.out.println("#提货减去200...............");
inventory.setQuantity(inventory.getQuantity()-200);
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
}
差点忘了,在悲观锁和乐观锁的测试运行之前一定要初始化数据
舒适化数据类如下
- import org.hibernate.Session;
- import org.hibernate.Transaction;
-
- public class InitialData {
- public static void main(String args[]){
- Session session=null;
- Transaction tx=null;
- try{
- session=HibernateUtil.getSession();
- tx=session.beginTransaction();
- Inventory inventory=new Inventory();
- inventory.setItemName("Viager");
- inventory.setQuantity(1000);
- session.save(inventory);
- tx.commit();
- }catch(Exception e){
- e.printStackTrace();
- tx.rollback();
- }finally{
- HibernateUtil.colseSession(session);
- }
- }
- }
import org.hibernate.Session;
import org.hibernate.Transaction;
public class InitialData {
public static void main(String args[]){
Session session=null;
Transaction tx=null;
try{
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Inventory inventory=new Inventory();
inventory.setItemName("Viager");
inventory.setQuantity(1000);
session.save(inventory);
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
}
}
通过以上的测试 我们可以对Hibernate悲观锁和乐观锁有个比较清晰的认识!!!
相关推荐
在处理并发问题时,Hibernate提供了悲观锁和乐观锁两种机制。 悲观锁假设并发环境中的冲突是常态,因此在读取数据时就立即锁定,直到事务结束才释放。在Hibernate中,可以通过设置`@LockModeType.PESSIMISTIC_READ`...
悲观锁和乐观锁是两种常见的锁定策略,它们各有特点,适用于不同的场景。 **悲观锁**(Pessimistic Lock)的名字来源于其悲观的态度,它认为数据随时可能被其他事务修改,因此在读取数据时就立即进行加锁,防止其他...
悲观锁和乐观锁各有优缺点,选择哪种锁机制取决于具体的应用场景和需求。悲观锁适合数据修改频繁且对数据一致性要求较高的场景;而乐观锁适用于数据修改较少且并发量较大的场景。在实际应用中,可以根据具体情况灵活...
Hibernate 锁机制_悲观锁和乐观锁 Hibernate 锁机制是指在... Hibernate 的锁机制可以分为悲观锁和乐观锁两种,悲观锁通过数据库层次的锁定来实现,而乐观锁通过应用程序上的逻辑实现版本控制的方法来维护正确的数据。
并发控制—悲观锁和乐观锁
悲观锁和乐观锁是两种常见的并发控制策略,用于在多任务环境下确保数据一致性。它们各自有不同的工作原理和适用场景。 悲观锁(Pessimistic Lock)正如其名,它假设并发环境中会发生频繁的冲突,因此在读取数据时就...
十三、关于悲观锁和乐观锁
Hibernate 实现悲观锁和乐观锁代码介绍 Hibernate 是一个基于 Java 的持久层框架,它提供了多种锁机制来实现事务的隔离性和一致性。在本文中,我们将详细介绍 Hibernate 实现悲观锁和乐观锁的代码实现,并讨论 ...
36谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景?
所谓乐观锁,重视假设最好的情况,每次去拿数据都认为别人不会修改,所以不会上锁,但是会在更新时判断一下在此期间这个数据有没有更改,使用版本号机制和CAS算法实现,乐观锁适用于多读的应用类型,这样可以提高...
介绍数据库事务的定义和事务带来的问题,详细讲解乐观锁与悲观锁的区别
### 面试必备之乐观锁与悲观锁详解 #### 一、悲观锁与乐观锁的概念 悲观锁和乐观锁是计算机科学中用于处理并发控制的两种不同策略,它们主要应用于多线程环境下数据的一致性和完整性保护。两种锁的设计哲学反映了...
在Java的持久化框架Hibernate中,悲观锁和乐观锁是两种重要的并发控制策略,它们用于管理数据库中的数据在多线程环境下的访问安全。本文将深入探讨这两种锁机制的原理、应用场景及其区别。 首先,我们来理解悲观锁...
在ThinkPHP框架中,常见的有乐观锁和悲观锁两种机制。本文将通过实例分析这两种锁在ThinkPHP框架中的应用,以及它们各自的优缺点。 首先,让我们从乐观锁开始了解。乐观锁机制假设多个事务在处理数据时很少发生冲突...
总结来说,Hibernate的悲观锁和乐观锁是两种不同的并发控制策略,悲观锁倾向于预防并发冲突,适合并发较低但需要保证数据一致性的情景;而乐观锁则在并发较高的情况下更优,通过版本控制减少锁定,但在冲突处理上...
【描述】:“面试必备之乐观锁与悲观锁.pdf”涉及的是并发控制中的两种重要锁机制——悲观锁和乐观锁,它们是多线程环境下确保数据一致性的重要手段。 【标签】:“求职面试 多线程” 【正文】: 悲观锁和乐观锁...