一、事務
1、什麼是事務:
事務:事物指的是邏輯上的一組操作,組成這一組操作的邏輯單元要麼全成功,要麼全失敗
2、事務的特性:
(1)原子性:代表事務不可分割。
(2)一致性:代表事務執行的前後,數據的完整性要保證一直。
(3)隔離性:代表的是一個事務執行的過程當中,不應該受到其他事務的干擾。
(4)持久性:代表一個事務執行完成後數據就持久到數據庫當中(提交或回滾)。
3、如果我們不考慮事務的隔離性,就會引發一些安全性的問題
(一)讀的問題
(1)髒讀:一個事務讀到另外一個事務未提交的數據
(2)不可重複讀:一個事務讀到了另一個事務已經提交的update的數據,導致在前一個事務多次查詢結果不一致
(3)虛度/幻讀:一個事務讀到另外一個事務已經提交的但是insert的數據,導致在前一個事務當中多次查詢的結果不一致
(二)寫的問題
(1)引發兩類丟失更新
4、讀問題的解決
(一)設置事務的隔離級別
1、Read uncommitted:未提交讀–以上的讀問題都會發生
2、Read commited:解決髒讀,但是不可重複讀和虛讀有可能發生(Oracle默認隔離級別)
3、Repeatable read:解決髒讀和不可重複讀,但是虛讀是有可能發生的(MySQL默認隔離級別)
4、Serializable:解決所有的讀問題(不能有事物的併發)(安全性高效率低)
二、Hibernate當中要設置事務的隔離級別
核心配置文件hibernate.cfg.xml當中配置對應的屬性
4是mysql的默認隔離級別
8是Oracle的默認隔離級別
三、Service層事務
1、Hibernate如何解決Service的事務管理
2、使用getCurrentSession獲取當前線程的session對象
(1)改寫工具類
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/* Hibernate的工具類*/
public class HibernateUtils {
public static final Configuration cfg;
public static final SessionFactory sf;
static {
cfg = new Configuration().configure();
sf = cfg.buildSessionFactory();
}
public static Session openSession() {
return sf.openSession();
}
public static Session getCurrentSession() {
return sf.getCurrentSession();
}
}
<!-- 設置事務隔離級別 -->
<property name="hibernate.connection.isolaction">4</property>
(2)配置完成(hibernate的核心配置文件當中)
<!-- 配置當前線程來綁定的session -->
<property name="hibernate.current_session_context_class">thread</property>
getCurrentSession獲取當前線程的session對象,創建session對象之後不需要調用close方法,在線程結束的時候會自動將session關閉
(3)測試類
package com.itzheng.hibernate.demo01;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.itzheng.hibernate.utils.HibernateUtils;
/*
* 測試當前線程綁定的Session
*/
public class HibernateDemo04 {
@Test
public void demo01() {
//會按照配置的好的事務處理方式去存儲數據
Session session = HibernateUtils.getCurrentSession();//保證每一個對象在調用該方法的時候都使用的是同一個session
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_name("王西");
session.save(customer);
transaction.commit();
//session.close();不需要二次關閉session。因爲在當前線程結束的時候就會關閉session對象,也就緩存
}
}