持續輸出面試題之Hibernate篇

程式媛小紅發表於2020-08-07

開篇介紹

大家好,我是Java最全面試題庫的提褲姐,今天有點事更新晚了,但是斷更是不可能斷更的,這輩子都不可能斷更的。好了,今天這篇是JavaEE系列的第六篇,主要總結了Hibernate相關的問題,在後續,會沿著第一篇開篇的知識線路一直總結下去,做到日更!如果我能做到百日百更,希望你也可以跟著百日百刷,一百天養成一個好習慣。

Hibernate執行流程?

  • 讀取並解析配置檔案
  • 讀取並解析對映資訊,建立SessionFactory
  • 開啟Sesssion
  • 建立事務Transation
  • 持久化操作
  • 提交事務
  • 關閉Session
  • 關閉SesstionFactory

什麼是Hibernate的併發機制?怎麼去處理併發問題?

Hibernate併發機制:
1、Hibernate的Session物件是非執行緒安全的,對於單個請求,單個會話,單個的工作單元(即單個事務,單個執行緒),它通常只使用一次, 然後就丟棄。
如果一個Session 例項允許共享的話,那些支援併發執行的,例如Http request,session beans將會導致出現資源爭用。
如果在Http Session中有hibernate的Session的話,就可能會出現同步訪問Http Session。只要使用者足夠快的點選瀏覽器的“重新整理”, 就會導致兩個併發執行的執行緒使用同一個Session。

2、多個事務併發訪問同一塊資源,可能會引發第一類丟失更新,髒讀,幻讀,不可重複讀,第二類丟失更新一系列的問題。

解決方案:
①設定事務隔離級別
Serializable:序列化。隔離級別最高
Repeatable Read:可重複讀
Read Committed:已提交資料讀
Read Uncommitted:未提交資料讀。隔離級別最差

②設定鎖:樂觀鎖和悲觀鎖
樂觀鎖:使用版本號或時間戳來檢測更新丟失,在的對映中設定 optimistic-lock=”all”可以在沒有版本或者時間戳屬性對映的情況下實現 版本檢查,此時Hibernate將比較一行記錄的每個欄位的狀態 行級悲觀鎖:Hibernate總是使用資料庫的鎖定機制,從不在記憶體中鎖定物件!只要為JDBC連線指定一下隔 離級別,然後讓資料庫去搞定一切就夠了。類LockMode 定義了Hibernate所需的不同的鎖定級別:

  • LockMode.UPGRADE
  • LockMode.UPGRADE_NOWAIT
  • LockMode.READ

Hibernate中的三種資料狀態?

臨時態(瞬時態/Transient)
不存在於session中,也不存在於資料庫中的資料,被稱為臨時態。
比如:剛剛使用new關鍵字建立出的物件。

持久態(Persistent)
存在於session中,事務還未提交,提交之後最終會進入資料庫的資料,被稱為持久態。
比如:剛剛使用session.save()操作的物件。

遊離態(脫管態/Detached)
存在於資料庫中,但不存在於session中的資料,被稱為遊離態。
比如:使用了session.save(),並且事務已經提交之後,物件進入資料庫,就變成了遊離態。

Hibernate 的三種狀態之間如何轉換?

當物件由瞬時狀態(Transient)一save()時,就變成了持久化狀態
當我們在Session裡儲存物件的時候,實際是在Session的Map裡存了一份, 也就是它的快取裡放了一份,然後,又到資料庫裡存了一份,在快取裡這一份叫持久物件(Persistent)。 Session 一 Close()了,它的快取也都關閉了,整個Session也就失效了,這個時候,這個物件變成了遊離狀態(Detached),但資料庫中還是存在的。
當遊離狀態(Detached)update()時,又變為了持久狀態(Persistent)。
當持久狀態(Persistent)delete()時,又變為了瞬時狀態(Transient), 此時,資料庫中沒有與之對應的記錄。

介紹一下Hibernate 的快取機制?

hibernate分為2級快取
一級快取又叫session快取,又叫事務級快取,生命週期從事務開始到事務結束,一級快取是hibernate自帶的,暴力使用,當我們一建立session就已有這個快取了。資料庫就會自動往快取存放,
二級快取是hibernate提供的一組開放的介面方式實現的,都是通過整合第三方的快取框架來實現的,二級快取又叫sessionFactory的快取,可以跨session訪問。常用的EHcache、OScache,這個需要一些配置。

當我們每次 查詢資料的時候,首先是到一級快取檢視是否存在該物件,如果有直接返回,如果沒有就去二級快取進行檢視,如果有直接返回,如果沒有在傳送SQL到資料庫查詢資料,
當SQL傳送查詢回該資料的時候,hibernate會把該物件以主鍵為標記的形式儲存到二級快取和一級快取,如果返回的是集合,會把集合打散然後以主鍵的形式儲存到快取。一級快取和二級快取只針對以ID查詢的方式生效,get、load方法。

說一下Hibernate的幾個核心介面?

  • Configuration 介面:配置Hibernate,根據其啟動hibernate,建立SessionFactory 物件
  • SessionFactory 介面:初始化Hibernate,充當資料儲存源的代理,建立session 物件,sessionFactory 是執行緒安全的,意味著它的同一個例項可以被應 用的多個執行緒共享,是重量級、二級快取
  • Session 介面:負責儲存、更新、刪除、載入和查詢物件,是執行緒不安全的, 避免多個執行緒共享同一個session,是輕量級、一級快取
  • Transaction 介面:管理事務
  • Query 和Criteria 介面:執行資料庫的查詢。

get 和 load 的區別?

  • get 是立即載入,load 是延時載入
  • get 會先查一級快取,再查二級快取,然後查資料庫;

load 會先查一級快取,如果沒有找到,就建立代理物件,等需要的時候去查詢二級快取和資料庫。(這裡就體現 load 的延遲載入的特性。)

  • get 如果沒有找到會返回 null,load 如果沒有找到會丟擲異常
  • 當我們使用 session.load()方法來載入一個物件時,此時並不會發出 sql 語句,當前得到的這個物件其實是一個代理物件,這個代理物件只儲存了實體物件的 id 值,只有當我們要使用這個物件,得到其它屬性時,這個時候才會發出 sql 語句,從資料庫中去查詢我們的物件;

相對於 load 的延遲載入方式,get 就直接的多,當我們使用session.get()方法來得到一個物件時,不管我們使不使用這個物件,此時都會發出 sql 語句去從資料庫中查詢出來。

Hibernate 有幾種查詢方式?

4種:

  • HQL 通過Hibernate提供的查詢語言進行查詢。Hibernate Query lanague
  • EJBQL(JPQL 1.0) 是EJB提供的查詢語言
  • QBC(query by cretira)通過Cretira介面進行查詢
  • QBE(query by Example) 通過Example程式設計介面進行查詢

從功能強弱上排序:
NativeSQL > HQL > EJBQL(JPQL 1.0) >QBC(query by cretira) >QBE(query by Example)

QBC(Query By Criteria)查詢方式是 Hibernate 提供的“ 更加物件導向”的一種檢索方式。 QBC 在條件查詢上比 HQL 查詢更為靈活,而且支援執行時動態天生查詢語句。

Hibernate中save、update和saveOrUpdate方法的不同之處?

save:
執行儲存操作的,對一個新new出來的物件進行儲存,資料庫中沒有這個物件,如果資料庫中有,會報錯說有重複的記錄
update:
如果是對一個已經存在的託管物件進行更新,要使用update方法了,資料中有這個物件
saveOrUpdate:
這個方法是更新或者插入,有主鍵就執行更新,如果沒有主鍵就執行插入。是根據實體類物件的狀態做的不同操作

在資料庫中條件查詢速度很慢的時候,如何優化?

  • 建索引
  • 減少表之間的關聯
  • 優化sql,儘量讓sql很快定位資料,不要讓sql做全表查詢,應該走索引,把資料量大的表排在前面
  • 簡化查詢欄位,沒用的欄位不要,已經對返回結果的控制,儘量返回少量資料

什麼是 Hibernate 延遲載入?

延遲載入機制:
延遲載入機制是為了避免一些無謂的效能開銷而提出來的,所謂延遲載入就是當在真正需要資料的時候,才真正執行資料載入操作。在 Hibernate 中提供了對實體物件的延遲載入以及對集合的延遲載入,另外在 Hibernate3 中還提供了對屬性的延遲載入。

延遲載入的過程:
通過代理(Proxy)機制來實現延遲載入。Hibernate 從資料庫獲取某一個物件資料時、獲取某一個物件的集合屬性值時,或獲取某一個物件所關聯的另一個物件時,由於沒有使用該物件的資料(除識別符號外),Hibernate 並不從資料庫載入真正的資料,而只是為該物件建立一個代理物件來代表這個物件,這個物件上的所有屬性都為預設值;只有在真正需要使用該物件的資料時才建立這個真正的物件,真正從資料庫中載入它的資料。

Hibernate 和 Mybatis 的區別?

相同點:

  • Hibernate 與 MyBatis 都可以是通過 SessionFactoryBuider 由 XML 配置檔案生成 SessionFactory,然後由

SessionFactory 生成 Session,最後由 Session 來開啟執行事務和 SQL 語句。其中 SessionFactoryBuider,
SessionFactory,Session 的生命週期都是差不多的。

  • Hibernate 和 MyBatis 都支援 JDBC 和 JTA 事務處理。

Mybatis 優勢:

  • MyBatis 可以進行更為細緻的 SQL 優化,可以減少查詢欄位。
  • MyBatis 容易掌握,而 Hibernate 門檻較高。

Hibernate 優勢:

  • Hibernate 的 DAO 層開發比 MyBatis 簡單,Mybatis 需要維護 SQL 和結果對映。
  • Hibernate 對物件的維護和快取要比 MyBatis 好,對增刪改查的物件的維護要方便。
  • Hibernate 資料庫移植性很好,MyBatis 的資料庫移植性不好,不同的資料庫需要寫不同 SQL。
  • Hibernate 有更好的二級快取機制,可以使用第三方快取。MyBatis 本身提供的快取機制不佳。

相關文章