3.1 hibernate持久化類及一級緩存

1.持久化類編寫規則java

Hibernate是持久化層的ORM映射框架,專一於數據的持久化工做。算法

持久化:所謂的持久化就是講內存中的數據永久保存到關係型數據庫中。數據庫

持久化類:其實所謂的持久化類指的是一個Java類與數據庫表創建了映射關係,那麼這個類稱爲是持久化類。其實,你能夠簡單的理解爲就是一個Java類,該類經過一個映射文件與數據庫的表創建了關係。持久化類的編寫規則以下:緩存

  1.持久化類提供無參數構造:由於在hibernate的底層須要使用反射生成類的實例;
  2.成員變量私有,提供共有get/set方法訪問.需提供屬性;由於Hibernate底層會將查詢到的數據進行封裝;
  3.持久化類中的屬性,應儘可能使用包裝類型:由於包裝類和基本數據類型的默認值不一樣,包裝類的類型語義描述更清晰,而基本數據類型不容易描述。舉個例子:假設表中有一列員工工資,若是使用double類型,若是這個員工工資忘記錄入到系統中,系統會將默認值0存入到數據庫,若是這個員工工資被扣完了,也會在系統中存入0。那麼這個0就有了多重含義,而若是使用包裝類型就會避免以上狀況,若是使用Double類型,忘記錄入工資就會存入null,而這個員工工資被扣完了,就會存入0,不會產生歧義。
  4.持久化類須要提供oid.與數據庫中的主鍵列對應;由於hibernate中須要用過這個惟一的標識oid區分在內存中是不是同一個持久化類實例。在java中經過地址區分是不是同一個對象的,在關係型數據庫的表中是經過主鍵區分是否同一條記錄。那麼hibernate就是經過這個oid來進行區分的。hibernate是不容許在內存中出現兩個oid相同的持久化對象的。
  5.不要用final修飾class:由於Hibernate中有延遲加載的機制,這個機制中會產生代理對象,hibernate產生代理對象使用的是字節碼的加強技術完成的,其實就是產生了當前類的一個子類對象實現的。若是使用了final修飾持久化類,那麼就不能產生子類,從而就不會產生代理對象,那麼Hibernate的延遲加載策略(是一種優化手段)就會失效。(hibernate使用cglib代理生成代理對象.代理對象是繼承被代理對象.若是被final修飾.將沒法生成代理.)網絡

持久化類咱們已經能夠正常編寫了,可是在持久化類中須要有一個惟一標識OID與表的主鍵去創建映射關係。並且主鍵通常咱們是不會讓客戶手動錄入的,通常咱們是由程序生成主鍵。那麼Hibernate中也提供了相應的主鍵生成的方式,那麼咱們來看下hibernate的主鍵生成策略。session

 

2. Hibernate主鍵生成策略框架

主鍵的類型:在講解Hibernate的主鍵生成策略以前,先來了解兩個概念,即天然主鍵和代理主鍵,具體以下:ide

  • 天然主鍵:表的業務列中,有某個業務列符合:必須有,而且不重複的特徵時,該列能夠做爲主鍵使用,稱之爲天然主鍵;例如在customer表中,若是把name字段做爲主鍵,其前提條件是:每個客戶的姓名不容許爲null,而且不容許客戶重名,而且不容許修改客戶姓名。儘管這是可行的,可是不能知足不斷變化的業務需求,一旦出現了容許客戶重名的業務需求,就必須修改數據模型,從新定義表的主鍵,這給數據庫的維護增長了難度。
  • 代理主鍵:表的業務列中,沒有某業務列符合:必須有,而且不重複的特徵時,建立一個沒有業務意義的列做爲主鍵;把不具有業務含義的字段做爲主鍵,稱之爲代理主鍵。該字段通常取名爲ID,一般爲整數類型,由於整數類型比字符串類型要節省更多的數據庫空間。在上面的例子中,顯然更合理的方式是使用代理主鍵。

Hibernate提供了幾個內置的主鍵生成策略,其經常使用主鍵生成策略的名稱和描述以下:性能

  • 天然主鍵類型
    • assigned:天然主鍵生成策略. hibernate不會管理主鍵值.由開發人員本身錄入;由java程序負責生成標識符,若是不指定id元素的generate屬性,則默認使用該主鍵生成策略。適用於天然主鍵。
  • 代理主鍵
    • sequence: Oracle中的主鍵生成策略.Hibernate根據底層數據庫序列生成標識符。條件是數據庫支持序列,適用於代理主鍵。
    • increment(瞭解): 主鍵自增.由hibernate來維護.每次插入前會先查詢表中id最大值.+1做爲新主鍵值;用於long、short、或int類型,由hibernate自動以遞增的方式生成惟一標識符,每次增量爲1。只有當沒有其它進程向同一張表中插入數據時纔可使用,不能再集羣環境下使用。適用於代理主鍵。
    • identity: 採用底層數據庫提供的主鍵生成標識符,條件是數據庫支持自動增加數據類型。在DB二、MySQL、MS SQLServer、Sybase和HypersonicSQL數據庫中可使用該生成器,該生成器要求在數據庫中把主鍵定義成爲自增加類型,適用於代理主鍵。
    • hilo(瞭解): 高低位算法.主鍵自增.由hibernate來維護.開發時不使用.
    • native:hilo+sequence+identity 自動三選一策略.根據底層數據庫對自動生成標識符的能力來選擇identity、sequence、hilo三種生成器中的一種,適合跨數據庫平臺開發。適用於代理主鍵。
    • uuid: 產生隨機字符串做爲主鍵. 主鍵類型必須爲string 類型. Hibernate採用128位的UUID算法來生成標識符。該算法可以在網絡環境中生成惟一的字符串標識符,其UUID被編碼爲一個長度爲32位的十六進制字符串。這種策略並不流行,由於字符串類型的主鍵比整數類型的主鍵佔用更多的數據庫空間,適用於代理主鍵。

 

3. Hibernate持久化對象的三種狀態測試

瞭解了主鍵的生成策略以後,咱們能夠進一步來了解持久化類了。hibernate爲了更好地管理持久化類,特將持久化類分紅了三種狀態,分別是:瞬時態、持久態、託管態,一個持久化類的實例可能處於三種不一樣狀態中的某一種。

  • 瞬時狀態

沒有id,沒有在session緩存中;瞬時態就稱爲臨時態或者自由態,瞬時態的實例是由new命令建立、開闢內存空間的對象,不存在持久化標識oid(至關於主鍵值),還沒有與hibernate Session關聯,在數據庫中也沒有記錄,失去引用後將被JVM回收。瞬時狀態的對象在內存中是孤立存在的,與數據庫中的數據無任何關聯,僅是一個信息攜帶的載體。

  • 持久化狀態

有id,在session緩存中;持久態的對象存在持久化標識oid,加入到了Session緩存中,而且相關聯的Session沒有關閉,在數據庫中有對應的記錄,每條記錄只對應惟一的持久化對象,須要注意的是,持久化對象是在事務還未提交前變成持久態的。

  • 遊離|託管狀態

有id,沒有在session緩存中;託管態也稱離線態或者遊離態,當某個持久化狀態的實例與Session的關聯被關閉時就變成了託管態。託管態對象存在持久化標識oid,而且仍然與數據庫中的數據存在關聯,只是失去了與當前Session的關聯,託管狀態對象發生改變時,hibernate不能檢測到。

 

咱們以前已經介紹了持久化對象的三種狀態了,其實咱們主要去研究持久太對象就夠了,持久態對象其實有一個很是重要的特性:持久化對象能夠自動更新數據庫。

實例:

1. 編寫測試代碼

 1 @Test
 2     public void demo7() {
 3         // 開啓事務
 4         Transaction tx = session.beginTransaction();
 5         // 得到持久化對象
 6         Customer customer = session.get(Customer.class, 1l);
 7         customer.setCust_name("nakelulu");
 8         // 不調用session.update(customer);
 9         tx.commit();
10         session.close();
11     }
demo7

hibernate自動調用update方法。

 

4. hibernate的一級緩存

  • Hibernate緩存原理

緩存是計算機領域很是通用的概念。它介於應用程序和永久性數據存儲源(如硬盤上的文件或者數據庫)之間,其做用是下降應用程序直接讀寫永久性數據存儲源的頻率,從而提升應用的運行性能。緩存中的數據是數據存儲源中數據的拷貝。緩存的物理介質一般是內存。

Hibernate的緩存分爲一級緩存和二級緩存,hibernate的這兩級緩存都位於持久化層,存儲的都是數據庫數據的備份。其中第一級緩存爲Hibernate的內置緩存,不能被卸載。

Hibernate的一級緩存就是指Session緩存,Session緩存是一塊內存空間,用來存放相互管理的java對象,在使用Hibernate查詢對象的時候,首先會使用對象屬性的oid值在Hibernate的一級緩存中進行查找,若是找到匹配oid值得對象,就直接將該對象從一級緩存中取出使用,不會再查詢數據庫;若是沒有找到相同oid值的對象,則會去數據庫中查找相應的數據。

當從數據庫中查詢到所需的數據時,該數據信息也會放置到一級緩存中。Hibernate的一級緩存的做用就是減小對數據庫的訪問次數。 

  在Session接口的實現中包含一系列的Java集合,這些Java集合構成了Session緩存。只要Session實例沒有結束生命週期,存放在它緩存中的對象也不會結束生命週期。故一級緩存也被稱爲是Session基本的緩存。

Hibernate的一級緩存有以下特色:

1. 當應用程序調用Session接口的save()、update()、saveOrUpdate()時,若是Session緩存中沒有相應的對象,hibernate就會自動的把從數據庫中查詢到的相應對象信息加入到一級緩存中去。

2. 當調用Session接口的load()、get()方法,以及Query接口的list()、iterator()方法時,會判斷緩存中是否存在該對象,有則返回,不會查詢數據庫,若是緩存中沒有要查詢對象,再去數據庫中查詢對應對象,並添加到一級緩存中。

3. 當調用Session的close()方法時,Session緩存會被清空。

證實一級緩存的存在:

 1 @Test
 2     public void demo8() {
 3         Transaction tx = session.beginTransaction();
 4         Customer customer1 = session.get(Customer.class, 1l);        // hibernate查詢數據庫
 5         System.out.println(customer1);
 6         Customer customer2 = session.get(Customer.class, 1l);        // 不查詢數據庫
 7         System.out.println(customer1==customer2);                    // true
 8         System.out.println(customer2);
 9         tx.commit();
10         session.close();
11     }
demo8

  • 一級緩存的內部結構(快照區)

Hibernate向一級緩存放入數據時,同時複製一份數據放入到hibernate快照中,當使用commit()方法提交事務時,同時會清理Session的一級緩存,這時會使用oid判斷一級緩存中的對象和快照中的對象是否一致,若是兩個對象中的屬性發生變化,則執行update語句,將緩存的內容同步到數據庫,並更新快照:若是一致,則不執行update語句。Hibernate快照的做用就是確保一級緩存中的數據和數據庫中的數據一致。

相關文章
相關標籤/搜索