JavaEE學習筆記——Hibernate篇

文章部分內容整理自郭永鋒視頻教學內容!   

目錄

1、get和load方法的區別

2、查詢對象 

3、主鍵的生成策略

4、Hibernate 實體的狀態以及狀態之間的在轉換

5、一級緩存 

6、快照

7、Hibernate的多表關聯關係映射(一)(例:客戶訂單之間的關係爲一對多、多對一)

8、cascade級聯

9、Hibernate的多表關聯關係映射(二)(例:學生、課程之間的關係爲多對多)

10、悲觀鎖 【分爲讀鎖(共享鎖)和寫鎖(排它鎖)】

11、樂觀鎖

12、悲觀鎖和樂觀鎖的比較

13、二級緩存

 


 

1、get和load方法的區別

  • get方法是直接加載數據庫,返回一個對象
  • load的設計是懶加載,事先並不查詢數據庫,返回的是對象的一個代理,只有用到了對象的相關屬性纔會去查詢數據庫
紅圈中的標記說明返回的不是一個User對象,而是一個代理
load執行原理圖

2、查詢對象 

HQL:Hibernate Query Language的縮寫,就是Hibernate的查詢語言,面向對象查詢語言,最終底層要轉成面向數據庫查詢語言。

SQL:直接面向數據庫查詢語言。

  • Query 查詢對象:用於查詢的對象,可以設置查詢條件和分頁查詢。可使用HQL、SQL語句查詢。
  • Criteria查詢對象:hibernate提供純面向對象查詢語言,提供直接使用PO對象進行操作。

  • SQLQuery查詢對象使用原生的SQL語句查詢

3、主鍵的生成策略

<id name="uid" column="id">
   <!-- generator:id的生成策略
      increment:也會自動增長id,但是它的這種增長是自己Hibernate實現
                 執行select max(id) 查詢,這種會有線程併發問題
      sequence:一般在oracle數據庫才用
      hilo:hibernate自己實現的id規則【不用】
      native:【常用】
          如果是mysql數據庫,id會自動增長
          如果是oracle數據庫,會自動增長,sequence
      uuid:【常用】一個長字符串,需要把模型的id改成字符串
             保存的時候,不用自己設置ID,hibernate會設置id
      assigned:【常用】要手動設置id屬性
    -->
   <generator class="native"></generator>
</id>

4、Hibernate 實體的狀態以及狀態之間的在轉換

  • 瞬時狀態:session沒有緩存,數據庫也沒有記錄,oid沒有值
  • 持久狀態:session有緩存,數據庫也有記錄,oid有值
  • 脫管狀態/遊離狀態:session沒有緩存,數據庫有記錄,oid有值

瞬時狀態→持久狀態:執行save、update、saveOrUpdate

持久狀態→脫管狀態:session.close ()、session.clear()、session.evict(obj)5 

5、一級緩存 

一級緩存:又稱爲session級別的緩存。當獲得一次會話(session),hibernate在session中創建多個集合(map),用於存放操作數據(PO對象),爲程序優化服務,如果之後需要相應的數據,hibernate優先從session緩存中獲取,如果有就使用;如果沒有再查詢數據庫。當session關閉時,一級緩存銷燬。

證明一級緩存。第二次執行session.get()方法將會從session中取值,不會有SQL執行。判斷u1==u2結果爲true
當移除緩存後,第二次執行session.get()又會有SQL執行。將會有兩次select語句輸出

6、快照

快照作用:與一級緩存存放位置一樣,對一級緩存數據備份。保證數據庫的數據與 一級緩存的數據必須一致。

快照原理:在執行commit提交時,一級緩存將與快照進行對比,如果一級緩存修改了,將自動刷新一級緩存,執行update語句,將一級緩存的數據更新到數據庫。若一級緩存無變化,則不會執行update語句。

快照演示(一級緩存刷新) :session.flush()手動刷新,保持一級緩存與數據庫一致,此時會執行兩條update語句,如果去除flush代碼,只會產生一條update語句。

注意:HQL的結果會進行一級緩存,SQL的結果不會添加到一級緩存 

7、Hibernate的多表關聯關係映射(一)(例:客戶訂單之間的關係爲一對多、多對一)

實體類的編寫

Customer.hbm.xml

<hibernate-mapping package="com.gyf.hibernate.domain">

 

<class name="Customer" table="t_customer">

<id name="id" column="id">

<generator class="native"></generator>

</id>

<property name="name" length="20"></property>

 

<!-- 一個客戶有多個定單,Hibernate可以雙向描述一對多的關係

set中 name寫的是實例的屬性

  -->

<set name="orders">

<!-- column指的是Order表中的外鍵  -->

<key column="customer_id"></key>

<one-to-many class="Order"/>

</set>

</class>

</hibernate-mapping>

Order.hbm.xml

<hibernate-mapping package="com.gyf.hibernate.domain">

 

<class name="Order" table="t_order">

<id name="id" column="id">

<generator class="native"></generator>

</id>

 

<!-- 定單名稱 -->

<property name="name"></property>

 

<!-- 多個定單對應一個客戶,Hibernate可以雙向描述一對多的關係

set中 name寫的是實例的屬性

  -->

<many-to-one name="customer" class="Customer" column="customer_id"></many-to-one>

</class>

</hibernate-mapping>

8、cascade級聯

  • save-update級聯保存,級聯修改. 保存A(客戶)時,同時保存B(訂單)。
  • delete級聯刪除,刪除A時,同時刪除B。

  • delete-orphan孤兒刪除,解除關係,同時將B刪除,A存在的。

級聯在映射文件的<set>標籤中配置
級聯組合

如果需要配置多項,使用逗號分隔。<set cascade="save-update,delete">

all : save-update 和 delete 整合

all-delete-orphan : 三個整合

9、Hibernate的多表關聯關係映射(二)(例:學生、課程之間的關係爲多對多)

實體類的編寫

Student.hbm.xml

Course.hbm.xml

10、悲觀鎖 【分爲讀鎖(共享鎖)寫鎖(排它鎖)

  •  讀鎖(共享鎖)【用的少】

 讀鎖可被其他線程所共享,如果是讀取的話大家都可以用這把鎖讀到數據。

原理:A線程打開事務並執行select * from table lock in share mode,查出數據,此時A線程擁有了讀鎖。

接着B線程打開事務並執行select * from table lock in share mode,查出數據,此時讀鎖轉移到了B線程。

這時A執行update語句,會發現A進程停住不動了,update語句處於等待執行狀態。

這時因爲讀鎖在B進程身上,當B進程提交事務後,會發現A進程的update語句執行成功。

  • 寫鎖(排它鎖)【用的多】

寫鎖不能共享,只要有人爲數據加入了寫鎖,其他人就不能爲數據加任何鎖(可以鎖一張表,或者鎖一行記錄

原理:A線程打開事務並執行select * from table for update,查出數據,此時A線程擁有了寫鎖。

接着B線程打開事務並執行select * from table for update,發現查不出數據,因爲寫鎖不能共享,此時鎖依然在A身上。

當A線程提交事務,B線程將會查出數據並打印。

Hibernate中添加寫鎖

11、樂觀鎖

樂觀鎖就是在表中添加一個version字段來控制數據不一致性

在PO對象(javabean)提供字段,表示版本字段。一般爲Integer

在映射文件中配置下Version,該字段由hibernate實現自增

原理:假如user表中有一行數據,屬性有username和version字段,其中username值爲"hd",version值爲0

A、B進程同時獲取該行數據得到version=0

A修改username字段值爲"hh",hibernate實現version字段值的自增,此時version=1

B進程同時也想修改username值爲"dd",但發現之前獲取到的version=0小於現在version=1,此時B的修改無效並報錯

12、悲觀鎖和樂觀鎖的比較

悲觀鎖由數據庫實現,樂觀鎖由hibernate實現。

樂觀鎖存在的問題:當前臺使用的語言和後臺hibernate使用的語言不同時,樂觀鎖將會失效。因爲樂觀鎖由hibernate實現,當前臺較先修改完數據後不能讓version字段自增,此時後臺檢測到前後version值一樣因此也能成功修改表數據。

13、二級緩存

二級緩存是sessionFactory級別緩存,整個應用程序共享一個會話工廠,共享一個二級緩存。

二級緩存由類級別緩存區集合級別緩存區時間戳緩存區查詢緩存區(又稱三級緩存)構成。

(1)適合放入二級緩存中的數據:很少被修改,不是很重要的數據, 允許出現偶爾的併發問題。

(2)不適合放入二級緩存中的數據:經常被修改,如財務數據, 絕對不允許出現併發問題。與其他應用數據共享的數據。

Hibernate中只定義二級緩存接口,實現需要自己選擇提供商,通常選擇EHCache

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章