文章部分內容整理自郭永鋒視頻教學內容!
目錄
7、Hibernate的多表關聯關係映射(一)(例:客戶訂單之間的關係爲一對多、多對一)
9、Hibernate的多表關聯關係映射(二)(例:學生、課程之間的關係爲多對多)
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。