Hibernate 中的常見坑
1. 前言
框架方便了開發(fā)者的工作,但是運行速度并沒有原生的快。原生開發(fā)是直接告訴 JVM 要做什么,框架則是曲線救國,JVM 需要繞些圈子才明白開發(fā)者的意圖。
顯然,框架是要以更多性能消耗、運行速度作為代價的。
本節(jié)課,和大家聊一聊使用 Hibernate 中可能遇到的坑。避開這些坑,真正享受 Hibernate 帶給開發(fā)者的福利。
2. 常見的坑
2.1 延遲加載
延遲加載是 Hibernate 提供的一種性能優(yōu)化方案,但是,使用時需要注意,必須保持在 Session 生命周期之內(nèi)。
Hibernate 中的延遲加載有 2 種情形,
- 如 load()方法。直接調(diào)用 load()方法只會產(chǎn)生一個代理對象,只有當訪問屬性的 get()方法時,才會訪問數(shù)據(jù)。
- one-to-many、many-to-one、many-to-many 中也可以設置延遲加載,只有訪問與當前查詢相關聯(lián)的關系表中的數(shù)據(jù)時,才會進行數(shù)據(jù)加載。
因為 Session 生命周期較短,如果要跨組件使用延遲加載功能, 則需保持 Session 生命周期與請求過程相同。WEB 項目開發(fā)中,Hibernate 提供有 OpenSessionInViewFilter 過濾器,用來保證請求開始和響應結束的時候,使用同一個 Session。請求開始創(chuàng)建 Session,響應結束關閉 Session。
使用時,這里面會有 1 個坑:不能使用重定向,因為重定向上本質(zhì)上是兩次請求。
2.2 save ()與 merge()
這兩個方法都可以接收對象作為參數(shù),但是,save()會把傳入的對象轉(zhuǎn)換成持久化狀態(tài) ,且返回保存成功后數(shù)據(jù)的主鍵。
merge()會返回一個對象,返回的此對象才具有持久化狀態(tài)。
這里的坑就是千萬別誤以為傳遞給 merge()方法的對象具有持久化狀態(tài)。
2.3 持久化狀態(tài)
持久化狀態(tài)的 PO 對象具有同步數(shù)據(jù)庫的能力,但是,請注意,持久化狀態(tài)只能是在 Session 生命周期之內(nèi)。現(xiàn)在的項目都是采用的分層體系結構。所以,不要指望業(yè)務組件從數(shù)據(jù)層組件中獲取的對象還具有持久化能力,除非你不關閉 Session。
這里的坑就是,持久化狀態(tài)的對象是有時效性的。
2.4 序列化的
從代碼規(guī)范上講,持久化對象是一定要實現(xiàn)序列化接口的,保證能在異構化系統(tǒng)或網(wǎng)絡中進行數(shù)據(jù)傳輸。
這里有坑就是實現(xiàn)序列化一定要成為持久化對象的標配。
2.5 級聯(lián)操作
Hibernate 提供的級聯(lián)操作帶來了很多方便。
但是,特別是在雙向關聯(lián)映射的情況下,不要把兩邊的級聯(lián)操作全部打開,否則會把不該刪除的數(shù)據(jù)刪除掉。
測試數(shù)據(jù)被級聯(lián)刪除倒無所謂,真實數(shù)據(jù)被刪除了,可能就欲哭無門。
2.6 緩存的使用
Session 級別緩存的應用價值不大,使用 Session 操作完畢后,盡可能進行緩存清理。
SessionFactory 二級緩存需要打開后才能使用,而且一般是依賴第三方插件。緩存可以提高查詢數(shù)據(jù)的速度,但是緩存本身需要消耗資源,所以,緩存的使用需要酌情考慮。
這里有坑就是不要濫用緩存,需要緩存的對象也是需要特別指定的。如此繁瑣,相必 HIbernate 也怕你濫用緩存。
2.7 更新和刪除
更新和刪除之前,一定要先從數(shù)據(jù)庫中查找到對應數(shù)據(jù)。更新和刪除都是針對于數(shù)據(jù)庫中的數(shù)據(jù)。
這個坑,經(jīng)常發(fā)生在我面授的學生中。
2.8 和其它框架整合
Hibernate 只是解決 JDBC 的問題,在項目中,不可避免的需要和其它框架進行整合。如 Spring 之流,這里面會有一個很大的坑,就是版本兼容問題。
典型的表現(xiàn)就是明明添加了相應的包,但是,出現(xiàn) class not found。這時就要考慮是否是版本之間的兼容問題。
這個坑有的時候很讓人迷惑,明明剛剛添加了相應的包,卻告知不存在相應的類。
Spring Boot 提供了 DATA JPA 實現(xiàn),本質(zhì)上是使用 Hibernate 的持久化功能。Spring Boot 開箱即用,很好解決了版本的兼容性問題。建議大家使用。
2.9 hbm2ddl 功能
Hibernate 的 hbm2ddl 功能非常強大,使用時一定要注意,什么時候設置為 create,什么時候設置為 update。null
hbm2ddl 功能只用于測試、學習 Hibernate 時,強烈建議不要使用于正式環(huán)境,不要指望利用它進行數(shù)據(jù)庫設計。
就怕初學者一看有這么好用的東西,就不管不顧任何時候都使用。
3. 小結
所謂坑,就是你我所走過的路。我遇到的你不一定會遇到,你遇到的我也不一定會碰到。所以,沒有任何一個人能告訴你所有。本課程是引路人,走完所有的路程還是要靠自己。
使用 Hibernate 時,總會出現(xiàn)這樣或那樣的問題,但是,要相信問題肯定能得到解決。本節(jié)課通過一些常見問題的解析,讓大家少走彎路。
經(jīng)驗還是需要大家自己積累,祝好運。