1. 程式人生 > >事務&Hibernate中指定隔離級別

事務&Hibernate中指定隔離級別

事務

l  事務:一組業務操作,要麼全部成功,要麼全部不成功。

在Hibernate中設定自動提交事務:

<!-- hibernate.connection.autocommit: 事務自動提交 (真正開發時,不用)
		<property name="hibernate.connection.autocommit">true</property>
	-->

l  特性:ACID

       原子性:整體

       一致性:資料

       隔離性:併發

       永續性:結果

l  隔離問題:

       髒讀:一個事務讀到另一個事務未提交的內容

       不可重複讀:一個事務讀到另一個事務已提交的內容(insert)

       虛讀(幻讀):一個事務讀到另一個事務已提交的內容(update)

l  隔離級別--解決問題

       readuncommittd,讀未提交。存在3個問題。

       readcommitted,讀已提交。解決:髒讀。存在2個問題。

       repeatableread ,可重複讀。解決:髒讀、不可重複讀。存在1個問題。

       serializable,序列化。單事務。沒有問題。


hibernate設定隔離級別

l  在hibernate.cfg.xml 配置

       hibernate.connection.isolation4


<!-- 改變Hibernate連線資料庫的事務隔離級別
		1: 讀未提交
		2: 讀已提交
		4: 可重複讀
		8: 序列化
	 -->
	<property name="hibernate.connection.isolation">4</property>

lost update 丟失更新



l  悲觀鎖:(資料庫提供實現) . 預設認為一定會發送別人要修改我使用的資料. 那我就可以為我讀取的資料加鎖.

丟失更新肯定會發生。

       採用資料庫鎖機制。

       讀鎖:共享鎖。讀鎖可被其他執行緒所共享,如果是讀取的話大家都可以用這把鎖讀到資料.

              select.... from  ... lock in share mode;         select * from table lock in share mode(讀鎖、共享鎖)

       寫鎖:排他鎖。(獨佔)寫鎖不能共享,只要有人為資料加入了寫鎖,其他人就不能為資料加任何鎖.

              select... from  ....  for update      select * from table for update (寫鎖、排它鎖)


l  樂觀鎖:丟失更新肯定不會發生

       在表中提供一個欄位(版本欄位),用於標識記錄。如果版本不一致,不允許操作。



hibernate處理丟失更新

l  悲觀鎖:寫鎖


case:
package com.itheima.e_api;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.LockOptions;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;

import com.itheima.domain.Customer;
import com.itheima.utils.HibernateUtils;

public class Demo2 {
	@Test
	//悲觀鎖
	//寫鎖
	public void fun1(){
		Session session = HibernateUtils.openSession();
		session.beginTransaction();
		//------------------------------------------------
		Customer c
		 = (Customer) session.get(Customer.class, 1, LockOptions.UPGRADE);
		
		System.out.println(c);
		//------------------------------------------------
		session.getTransaction().commit();
		session.close(); // 遊離狀態
	}
	@Test
	//悲觀鎖
	//讀鎖
	public void fun2(){
		Session session = HibernateUtils.openSession();
		session.beginTransaction();
		//------------------------------------------------
		Customer c
		 = (Customer) session.get(Customer.class, 1, LockOptions.READ);
		
		System.out.println(c);
		//------------------------------------------------
		session.getTransaction().commit();
		session.close(); // 遊離狀態
	}
}


@Test
	public void demo01(){
		//1 查詢所有
		Session session = factory.openSession();
		session.beginTransaction();
		
		Customer customer = (Customer) session.get(Customer.class, 1 ,LockMode.UPGRADE);
		System.out.println(customer);
		
		session.getTransaction().commit();
		session.close();
	}



l  樂觀鎖:

       在PO物件(javabean)提供欄位,表示版本欄位。一般Integer

       在*.hbm.xml 檔案配置 <version name="...">

步驟一:在實體中加一個屬性(提供get和set)


步驟二:在hbm.xml中設定



<!-- 告訴Hibernate , 樂觀鎖的版本號的屬性名 -->
		<version name="version"></version>


步驟三:測試

@Test
	public void demo02(){
		//1 查詢所有
		Session session = factory.openSession();
		session.beginTransaction();
		
//		Order order = new Order();
//		order.setPrice(998d);
//		session.save(order);
		
		Order order = (Order) session.get(Order.class, 32);
		order.setPrice(889d);
		
		
		session.getTransaction().commit();
		session.close();
	}


case:

package com.itheima.e_api;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.LockOptions;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;

import com.itheima.domain.Customer;
import com.itheima.utils.HibernateUtils;

public class Demo3 {
	@Test
	//樂觀鎖
	public void fun1(){
		Session session = HibernateUtils.openSession();
		session.beginTransaction();
		//------------------------------------------------
		Customer c
		 = (Customer) session.get(Customer.class, 1);
		
		c.setName("tom");
		
		System.out.println(c);
		//------------------------------------------------
		session.getTransaction().commit();
		session.close(); // 遊離狀態
	}
	@Test
	//悲觀鎖
	//讀鎖
	public void fun2(){
		Session session = HibernateUtils.openSession();
		session.beginTransaction();
		//------------------------------------------------
		Customer c
		 = (Customer) session.get(Customer.class, 1, LockOptions.READ);
		
		System.out.println(c);
		//------------------------------------------------
		session.getTransaction().commit();
		session.close(); // 遊離狀態
	}
}