Hibernate、樂觀鎖和悲觀鎖

悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿數據的時候都認爲別人會修改,因此每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會block直到它拿到鎖。傳統的關係型數據庫裏邊就用到了不少這種鎖機制,好比行鎖,表鎖等,讀鎖,寫鎖等,都是在作操做以前先上鎖。html


樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數據的時候都認爲別人不會修改,因此不會上鎖,可是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可使用版本號等機制。樂觀鎖適用於多讀的應用類型,這樣能夠提升吞吐量,像數據庫若是提供相似於write_condition機制的其實都是提供的樂觀鎖。java


兩種鎖各有優缺點,不可認爲一種好於另外一種,像樂觀鎖適用於寫比較少的狀況下,即衝突真的不多發生的時候,這樣能夠省去了鎖的開銷,加大了系統的整個吞吐量。但若是常常產生衝突,上層應用會不斷的進行retry,這樣反卻是下降了性能,因此這種狀況下用悲觀鎖就比較合適。數據庫

悲觀鎖session

地址:http://blog.163.com/liuweiyoung@126/blog/static/1731310452013328114929783/app


樂觀鎖性能

Hibernate爲樂觀鎖提供了3中實現:測試

1. 基於versionui

2. 基於timestampthis

3. 爲遺留項目添加添加樂觀鎖spa

 

配置基於version的樂觀鎖:

實體:

public class Employee {

	private String id;
	private String name;
	private int ver;
	private Date addTime;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Date getAddTime() {
		return addTime;
	}
	public void setAddTime(Date addTime) {
		this.addTime = addTime;
	}
	public int getVer() {
		return ver;
	}
	public void setVer(int ver) {
		this.ver = ver;
	}
	
}
hbm.xml

<hibernate-mapping package="cn.model">
	<class name="Employee" table="EMPLOYEE">
		<id name="id" column="ID">
			<generator class="uuid"></generator>
		</id>
		<!--version標籤用於指定表示版本號的字段信息--> 
		<version name="ver" column="VER" type="int"></version>
		
		<!--timestamp標籤用於指定表示版本號的字段信息-->  
        <!-- <timestamp name="updateDate"column="updateDate"></timestamp>  -->
		<property name="name" column="NAME" type="java.lang.String"/>
		<property name="addTime" column="ADD_TIME" type="java.util.Date"/>
	</class> 
</hibernate-mapping>

測試代碼:

public void saveEmployee(){
		Session session=null;
		Transaction tran=null;
		try{
			Employee e1=new Employee();
			e1.setName("Tom");
			e1.setAddTime(new Date());
			
			Employee e2=new Employee();
			e2.setName("Javck");
			e2.setAddTime(new Date());
			
			session=HibernateSessionFactory.getSession();
			tran=session.beginTransaction();
			session.save(e1);
			session.save(e2);
			tran.commit();
		}catch(Exception e){
			if(session!=null){
				session.close();
			}
		}
	}
	
	public void updateEmployee(){
		Configuration configuration = new Configuration();
		configuration.configure();
		ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
		SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		
		Session s1=sessionFactory.openSession();
		Session s2=sessionFactory.openSession();
		Employee e1=(Employee) s1.get(Employee.class, "4028826750c780f00150c780f1f10000");
		Employee e2=(Employee) s2.get(Employee.class, "4028826750c780f00150c780f1f10000");
		
        System.out.println("v1="+e1.getVer()+"--v2="+e2.getVer());
        
		Transaction t2=s2.beginTransaction();
		e2.setName("第二次修改2");
		t2.commit();
		
		System.out.println("v1="+e1.getVer()+"--v2="+e2.getVer());
		
		Transaction t1=s1.beginTransaction();
		e1.setName("第一次修改1");
		t1.commit();
	}



而且數據庫提交的值也是第一次提交的值版本爲3

相關文章
相關標籤/搜索