事務&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(); // 遊離狀態
}
}