Hibernate從0開始,第一部分初涉Hibernate搭建第一個簡單的Hibernate框架
https://blog.csdn.net/hekaikai666/article/details/81672688
回顧與總結:
簡述上一章的主要內容:
(一)Hibernate框架的概念:數據持久層的ORM框架,主要作用是用於操作數據庫,簡化封裝了JDBC的操作
(二)Hibernate框架的優點:開發效率高、可移植性好、完全面向對象、多表級聯操作、精細數據緩存、延遲加載。
(三)Hibernate框架的缺點:特定SQL語句優化、大規模批量數據處理
(四)ORM對象映射關係:Hibernate屬於第四級(一共四級)
(五)Hibernate框架使用步驟:
1、創建數據庫;
2、創建項目並導入兩大核心包;
3、導入Hibernate主配置文件;
4、根據數據庫中的表創建相應的實體類;
5、編寫映射文件;
6、加載映射文件;
7、執行相關數據庫操作;
接下來,我們就應該學習如何操作數據庫。首先要了解幾個概念:SessionFactory和Session和Configuration,這三個都是Hibernate操作做數據庫常用的接口,那麼他們究竟是用來幹什麼的呢?
Session接口:
Session接口對於Hibernate以至於開發人員來說是一個非常重要的接口。Hibernate中,實例化的Session是的接口類,創建和銷燬它都不會佔用很多資源。這在實際項目 中確實很重要,因爲在客戶程序中,可能會不斷地創建以及銷燬Session對象,如果Session的開銷太大,會給系統帶來不良影響。但值得注意的是 Session對象是非線程安全的,因此在你的設計中,最好是一個線程只創建一個Session對象。
在Hibernate的設計者的腦中,他們將session看作介於數據連接與事務管理一種中間接口。我們可以將session想象成一個持久化對象的緩衝區,Hibernate能檢測到這些持久對象的改變,並及時刷新數據庫。我們有時也稱Session是一個持久層管理器,因爲它包含這一些持久層相關的操作,諸如存儲持久對象至數據庫,以及從數據庫從獲得它們。區別於JSP九大內置對象中的session,Hibernate的session不同於JSP應用中的HttpSession。當我們使用session這個術語時,我們指的是Hibernate中的session,我將HttpSesion對象稱爲用戶session。
SessionFactory接口:
這裏用到了一個設計模式――工廠模式,用戶程序從工廠類SessionFactory中取得Session的實例。(之後會詳細的講Java中的6中設計原則和23種設計模式)
SessionFactory並不是輕量級的!實際上它的設計者的意圖是讓它能在整個應用中共享。典型地來說,一個項目通常只需要一 個SessionFactory就夠了,但是當你的項目要操作多個數據庫時,那你必須爲每個數據庫指定一個SessionFactory。 所以SessionFactory中就是用來操作各種session的,具體詳解到下貼中關於緩存機制。 SessionFactory在Hibernate中實際起到了一個緩衝區的作用,它緩衝了Hibernate自動生成的SQL語句和一些其它的映射數據,還緩衝了一些將來有可能重複利用的數據。
Configuration接口 :
Configuration接口的作用是對Hibernate進行配置,以及對它進行啓動。在Hibernate的啓動過程中,Configuration類的實例首先定位映射文檔的位置,讀取這些配置,然後創建一個SessionFactory對象。相當於在Java類中繼承關係,而Configuration就是用來與SessionFactory來繼承操作的。
一、Session操作數據庫。
首先我們瞭解幾個代名詞:
DML--指的是數據操縱語言,eg:insert into ,update ,delete
DQL--數據庫查詢語言, eg:select
DDL--數據庫模式定義語言 eg:create alter drop
DCL==數據庫控制語言 eg:grant revoke
TCL--事務控制語言 eg:commit
DDL,DML,DCL,DQL,TCL共同組成數據庫的完整語言。
(一)那麼我們的DML數據操作語言就是基礎操作數據庫的語言,主要實現的功能是增、刪、改的語句,他們有一個共同的特點:數據操作需要開啓和關閉事務。當然也需要事務控制語句來提交。
首先提出一個獲取工廠類的方法:因爲使用session就需要創建項目有且僅有唯一的一個SessionFactory工廠。
public static SessionFactory getSessionFactory() {
// 實例化主配置加載Configuration類對象
Configuration cf = new Configuration();
// 加載項目主配置文件
cf.configure("hibernate.cfg.xml");
// 獲取sessionFactory工廠對象
SessionFactory factory = cf.buildSessionFactory();
// 返回SessionFactory對象
return factory;
}
數據庫增加操作:session.save(Object);需要注意的是添加事務要進行提交,任何執行都需要Session對象關閉。
/**
* 通過session對象添加數據
*
* @param factory
* sessionFactory工廠對象
*/
private static void insert(SessionFactory factory) {
// 通過工廠獲取Session 對象
Session session = factory.openSession();
// 使用對象開啓事務
Transaction begin = session.beginTransaction();
// 創建一個實體對象
Dept dept = new Dept(2, "凱寶寶自造有限公司", "西安");
// 使用Session往數據庫中插入一條數據
session.save(dept);
// 提交事務
begin.commit();
// 關閉session
session.close();
}
數據庫刪除操作:session.delete(Object);需要注意的是刪除事務要進行提交,任何執行都需要Session對象關閉,刪除需要操作2條SQL語句,第一句是查詢此條,然後執行第二條刪除。
/**
* 通過session對象刪除數據
*
* @param factory
* sessionFactory工廠對象
*/
private static void delete(SessionFactory factory) {
// 獲取session對象
Session session = factory.openSession();
// 開啓事務
Transaction begin = session.beginTransaction();
// 根據id查找要刪除的對象
Dept dept = (Dept) session.get(Dept.class, 3);
// 執行刪除
session.delete(dept);
// 提交事務
begin.commit();
// 關閉session
session.close();
}
數據庫修改操作:session.(); 需要注意的是,數據庫先進行查詢,然後進行數據刪除,在把新的數據加入,所以需要執行3條SQL語句。
/**
* 通過session對象修改數據
*
* @param factory
* sessionFactory工廠對象
*/
private static void update(SessionFactory factory) {
// 通過工廠獲取Session 對象
Session session = factory.openSession();
// 使用對象開啓事務
Transaction begin = session.beginTransaction();
// 創建一個對象
Dept dept = new Dept(3, "凱寶寶自造有限公司", "美國");
// 修改數據:先查詢表中是否有這條數據,沒有就插入,有就看數據是否一致,一致不做任何操作,如果不一致就執行操作修改
session.update(dept);
// 提交事務
begin.commit();
// 關閉session
session.close();
}
數據庫保存並修改:session.saveOrUpdate(Object);先查詢表中是否有這條數據,沒有就插入,有就看數據是否一致,一致不做任何操作,如果不一致就執行操作修改
/**
* 通過session對象修改數據
*
* @param factory
* sessionFactory工廠對象
*/
private static void update(SessionFactory factory) {
// 通過工廠獲取Session 對象
Session session = factory.openSession();
// 使用對象開啓事務
Transaction begin = session.beginTransaction();
// 創建一個對象
Dept dept = new Dept(3, "凱寶寶自造有限公司", "美國");
// 修改數據:先查詢表中是否有這條數據,沒有就插入,有就看數據是否一致,一致不做任何操作,如果不一致就執行操作修改
session.saveOrUpdate(dept);
// 提交事務
begin.commit();
// 關閉session
session.close();
}
(二)數據庫簡單的查詢操作:根據ID查詢一條屬性(對象中),數據庫中則需要調用兩個方法get() 或 load();
get():只要調用此方法就會立即向數據庫發送一條查詢語句;並可以返回查詢結果對象;屬於非延遲加載機制,當無法查詢到此id對應的對象數據時,會報出一個NullPointerException空指針異常。
load():只要訪問對象的非查詢屬性(ID)纔會對數據庫進行發送操作,屬於延遲加載機制。當無法查詢到此id對應的數據時,會報出一個ObjectNotFoundException對象未找到異常。
/**
* 根據ID查詢一個對象.
*
* @param factory
* sessionFactory工廠對象
*/
private static void select1(SessionFactory factory) {
// 獲取session對象
Session session = factory.openSession();
// 直接id查詢一個對象
Dept dept1 = (Dept) session.get(Dept.class, 10);
Dept dept = (Dept) session.load(Dept.class, 10);
System.out.println("load:"+dept.getDname());
// session中get和load的區別
// get只要調用get方法,就會把所有的字段加載到內存中,如果訪問不在id範圍內的屬性則會NullPointerException(空指針異常)
// load只要使用了返回的對象,纔會運行加載的方法(訪問非ID屬性)如果訪問不在id範圍內的屬性則會ObjectNotFoundException(對象未找到異常)
}
對於Session查詢獲取中使用get()和load()方法,當然會呈現不同的狀態,而在session中會有三中不同的對象存儲方式:臨時狀態、持久狀態、遊離狀態。
二、Hibernate中對象存儲的三種狀態。
a.臨時狀態:臨時狀態對象(瞬時態) 內存中有對象,數據庫中沒有與之相對應的數據
b.持久狀態:內存中有對象,數據庫中有與之對應的數據,當修改對象的屬性時,數據庫中的數據也會跟着自動更改
c.遊離狀態:遊離狀態對象 內存中有對象,數據庫中有與之對應的數據,但是對象處理離線狀態,修改對象的屬性,數據庫中數據不會跟着被修改
/**
* 臨時狀態對象(瞬時態) 內存中有對象,數據庫中沒有與之相對應的數據
* 什麼樣的對象是臨時狀態?新創建的對象;持久狀態的對象調用了delete()方法
*/
/**
* 持久狀態對象 內存中有對象,數據庫中有與之對應的數據,當修改對象的屬性時,數據庫中的數據也會跟着自動更改(緩存在session緩存中...)
* 什麼樣的對象是持久狀態的對象?新創建的對象調用了save()或者saveOrUpdate();通過get()或者load()方法從數據庫中加載出來的對象;遊離態對象調用了update或者saveOrUpdate將變回持久態
*/
/**
* 遊離狀態對象 內存中有對象,數據庫中有與之對應的數據,但是對象處理離線狀態,修改對象的屬性,數據庫中數據不會跟着被修改
* 什麼樣的對象是遊離態呢?session關閉時(.close());從session緩存中踢出了某個持久態對象(.evick());清空session緩存(.clear())
*/
臨時狀態和遊離狀態隨時都有可能被垃圾回收...
上面這些文字相信你也雲裏霧裏,那麼下面我來用一張圖來詳細解釋一下這三種狀態的轉換關係。
當創建new()一個新的對象的時候,所創建的對象就處於臨時狀態,此時的對象存儲與內存當中當調用了save()(非延遲加載)或者saveOrUpdate()(延遲加載,需要使用非查詢屬性之後方可執行)方法之後。與數據庫產生交互,對象也就變成持久狀態,在內存中和在數據庫中均有對象屬性存在,此時執行修改的方法,內存中和數據庫中的數據均做修改。當對象調用delete()方法後,刪除掉數據庫中的數據,對象中的屬性也就變成了臨時態,但是臨時態是不會被清理的。當session對象關閉,清除或者踢出的方法時,持久態的屬性也就變成了遊離態(對象依舊在內存中,但是與數據庫的連接已經斷開,所以執行增刪改的方法只會影響對象不會影響數據庫中的內容)當重新建立連接(創建新的session對象後)調用save()或者saveOrUpdate()方法,又將變成持久態。當程序關閉的時候,也就是遊離態的對象無法再進行操作的時候,就只能等待PC的垃圾處理機制,隨機的清理掉對象的屬性,但不會影響到數據庫的操作。
三、髒數據與刷新緩存
什麼是髒數據?爲什麼存在髒數據?
髒數據:當session緩存中持久態對象的數據發生了變化,而數據庫中的數據未發生改變,這個對象是髒對象(髒數據)。在數據庫技術中,髒數據在臨時更新(髒讀)中產生。事務A更新了某個數據項X,但是由於某種原因,事務A出現了問題,於是要把A回滾。但是在回滾之前,另一個事務B讀取了數據項X的值(A更新後),A回滾了事務,數據項恢復了原值。事務B讀取的就是數據項X的就是一個“臨時”的值,就是髒數據。
爲了針對出現髒數據的問題,session中有一種檢查機制,使數據庫中的數據與對象中的數據保持一致,就叫做髒檢查;髒檢查就是檢查數據庫中數據是否和session緩存中持久態對象數據一致,如果不一致,則在刷新緩存時,將數據庫中數據刷新爲與session緩存中一致。一句話:刷新數據庫中的數據和session對象中的數據保持一致。