1. Hibernate 的持久化類
1.1 什么是持久化類
- 持久化類: 就是一個 Java 類(JavaBean),這個 Java類與表建立了映射關系就可以是持久化類;
- 持久化類 = JavaBean + xxx.hbm.xml;
1.2 持久化類的編寫規則
- 提供一個無參數的構造方法,因為底層需要進行反射;
- 提供一個唯一的標識 OID, 即映射數據表主鍵;
數據庫中通過主鍵, Java 對象通過地址確定對象. 持久化類通過唯一標識 OID 確定記錄. - 所有屬性提供公有的 set 或者 get 方法;
- 標識屬性應盡量使用基本數據類型的包裝類;
1.3 自然主鍵和代理主鍵
- 自然主鍵: 對象本身的一個屬性. 例如,創建一個人員表,使用身份證號(唯一的)作為表的主鍵.
- 代理主鍵: 不是對象本身的一個屬性. 例如,創建一個人員表,為每個人員單獨創建一個作為主鍵的字段.
- 創建表時,盡量使用代理主鍵.
1.4 主鍵生成的策略
<id name="cust_id" column="cust_id">
// 主鍵的生成策略
<generator class="native"/>
</id>
increment
: 適用於 short, int, long 作為主鍵,不是使用的數據庫自動增長機制;- Hibernate 中提供的一種增長機制;
- 先進行查詢:
select max(id) from user
, 再進行插入,將查詢出的最大值+1 作為新記錄的主鍵; - 缺點:不能在集群環境下或者有並發訪問的情況下使用;
identity
: 適用於 short, int, long 作為主鍵,但是這個必須使用在自動增長的數據庫中.- 底層使用的是數據庫的自動增長機制;
sequence
: 適用於short, int, long 作為主鍵.- 底層使用的是序列的增長方式,例如 Oracle 數據庫.
uuid
: 適用於 char, varchar 類型的作為主鍵;- 使用隨機的字符串作為主鍵;
native
: 使用本地策略,根據底層的數據庫不同,自動選擇適用於該種數據庫的生成策略.- 如果底層使用的 MySql 數據庫,相當於
identity
; - 如果底層使用的是 Oracle 數據庫,相當於
sequence
;
- 如果底層使用的 MySql 數據庫,相當於
assigned
: 主鍵的生成不用 Hibernate 管理,必須手動設置主鍵;
2. Hibernate 持久化對象的狀態
2.1 Hibernate 持久化類的狀態
- Hibernate 為了管理持久化類,將持久化類分成了三個狀態:
- 瞬時態(Transient Object), 沒有持久化標識 OID,沒有被納入到 Session 對象的管理;
- 持久態(Persistent Object)
- 有持久化標識OID,已經被納入到 Session 對象的管理;
- 注意: 持久化持久態的對象有自動更新數據庫的能力!! 因為 Session 的一級緩存.
- 托管態(Detached Object), 有持久化標識 OID,沒有被納入到 Session 對象的管理;
2.2 Hibernate 持久化對象的狀態轉換
- 瞬時態
- 獲得瞬時態對象:
User user = new User()
; - 瞬時態對象轉換成持久態:
save() 或 saveOrUpdate()
; - 瞬時態對象轉換成托管態(不推薦):
user.setId()
;
- 獲得瞬時態對象:
- 持久態
- 獲得持久態的對象:
get() 或 load()
; - 持久態轉換成瞬時態對象:
delete()
; - 持久態對象轉成托管態對象:
session 的 close() 或 evict() 或 clear()
- 獲得持久態的對象:
- 托管態
- 托管態轉換成瞬時態:
user.setId(null)
; - 托管態轉換成持久態:
update() 或 saveOrUpdate()
;
- 托管態轉換成瞬時態:
3. Hibernate 的一級緩存
3.1 什么是緩存
- 緩存其實就是一塊內存空間,將數據源(數據庫或者文件)中的數據存放到緩存中,再次獲取的時候,直接從緩存中獲取.
可以提升程序的性能.
3.2 Hibernate 框架提供了兩種緩存
-
一級緩存
- 自帶的,不可卸載的;
- 一級緩存的生命周期與 session 一致, 一級緩存稱為 session 級別的緩存;
-
二級緩存
- 二級緩存可以在多個 session 中共享數據;
- 二級緩存稱為 sessionFactory 級別的緩存;
- 二級緩存是為了增強一級緩存,一級緩存的生命周期比較短暫;
- 二級緩存默認沒有開啟,需要手動配置才可以使用;
-
session 對象的緩存概述
- Session 對象中有一系列 java 的集合,這些集合構成了一級緩存;
-
Session 中與一級緩存相關的方法
session.clear()
: 清空一級緩存;session.evict(Object entity)
: 從一級緩存中清除指定的實體對象;session.flush()
: 刷出緩存;
-
Hibernate 框架是如何做到數據發生變化時,進行同步操作的呢?
4. Hibernate 中的事務和並發
4.1 Hibernate 框架中設置隔離級別
- 需要在 hibernate.cfg.xml 的配置文件中通過標簽來配置;
<property name="hibernate.connection.isolation">4</property>
- "1"表示
Read uncommitted isolation
- "2"表示
Read committed isolation
- "4"表示
Repeatable read isolation
- "8"表示
Serializable isolation
4.2 丟失更新的問題
-
如果不考慮隔離性,也會產生寫入數據的問題,即丟失更新的問題;
-
例如: A 和 B 兩個事務同時對某一條記錄做修改,就會引發丟失更新的問題;
-
解決方案
- "悲觀鎖"
- 采用的是數據庫提供的一種鎖機制,如果采用了這種機制,在SQL語句的后面添加
for update
子句 - 當 A 事務在操作該條記錄時,會把該條記錄鎖起來,其他事務是不能操作這條記錄的;
- 只有當 A 事務提交后,鎖釋放了,其他事務才能操作該條記錄;
- 采用的是數據庫提供的一種鎖機制,如果采用了這種機制,在SQL語句的后面添加
- "樂觀鎖"
- 采用版本號的機制來解決,會在表結構添加一個字段
version=0
,默認值為 0; - 當 A 事務在操作完該條記錄,提交事務時,會先檢查版本號,只有版本號值相同,才可以提交事務.
同時,更新版本號version=1
; - 當 B 事務在操作完該條記錄,提交事務時,會先檢查版本號,如果發現版本號不同,程序會拋出異常.
- 采用版本號的機制來解決,會在表結構添加一個字段
- "悲觀鎖"
-
Hibernate 框架解決丟失更新的問題
- "悲觀鎖":較少使用,效率慢
- "樂觀鎖"
- 在對應的 JavaBean 中添加一個屬性,名稱可以是任意的.並提供 get 和 set 方法.
例如:private Integer version;
- 在映射的配置文件中,提供
<version name="version"/>
標簽即可;
- 在對應的 JavaBean 中添加一個屬性,名稱可以是任意的.並提供 get 和 set 方法.
4.3 綁定本地 Session
- JavaWeb 中的事務,需要在業務層使用 Connection 來開啟事務
- 一種是通過參數的方式傳遞;
- 另一種是把 Connection 綁定到 ThreadLocal 對象中;
- Hibernate 框架,使用 session 對象開啟事務.框架提供了 ThreadLocal 的方式,傳遞 session 對象
// 需要在 hibernate.cfg.xml 的配置文件中提供如下配置
<property name="hibernate.current_session_context_class">thread</property>
// 重寫 HiberanteUtils 工具類
public class HibernateUtils {
private static final Configuration CONFIG;
private static final SessionFactory FACTORY;
static{
CONFIG = new Configuration().configure();
FACTORY = CONFIG.buildSessionFactory();
}
public static Session getCurrentSession(){
// 從 ThreadLocal 中獲取當前 session 對象
// 該對象不用再手動關閉,線程結束了,會自動關閉.
return FACTORY.getCurrentSession();
}
}
參考資料