zoukankan      html  css  js  c++  java
  • 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) 


     

  • 相关阅读:
    SuiteScript > Script Queue Monitor (Beta)
    Mac > MacBook Pro的移动硬盘方案
    财务报表 > 现金流表的直接法,间接法,Cash Flow from Operating Activites
    税收基础知识 > 三税(营业税, 增值税, 所得税) + 关税
    Netsuite > Hierarchy of transactions in Inventory cost calculation
    Javascript > Eclipse > problems encountered during text search
    Javascript > Eclipse > 自动代码规范化
    嵌入式Linux > 简易安装思路,步骤记录
    Netsuite > Employee Record Name维护规则
    POSTMAN as debugger for integration APPs
  • 原文地址:https://www.cnblogs.com/xiaoqiangzhaitai/p/5429462.html
Copyright © 2011-2022 走看看