1. 程式人生 > >hibernate常見面試題詳解

hibernate常見面試題詳解

整理hibernate常見面試題

  1. 簡述hibernate執行原理或者工作原理
  2. 簡述hibernate的get和load方法區別
  3. 簡述hibernate資料三種狀態
  4. 簡述hibernate的快取機制
  5. 簡述hibernate中getCurrentSession和openSession區別
  6. 簡述hibernate的樂觀鎖和悲觀鎖
  7. 簡述hibernate的懶載入機制
  8. 簡述hibernate的事務機制

1、hibernate執行原理: 
hibernate裡面提供了3個核心介面 
Configuration、SessionFactory、Session 
1、hibernate啟動的時候利用Configuration讀取xml配置檔案 
2、通過配置檔案建立SessionFactory物件,初始化hibernate基本資訊 
3、獲取session然後呼叫CRUD方法進行資料操作,hibernate會把我們的資料進行三種狀態的劃分,然後根據狀態進行管理我們的資料,對應的傳送SQL進行資料操作 
4、關閉session,如果有事務的情況下,需要手動獲取事務並開啟,然後事務結束後提交事務。 
5、在提交事務的時候,去驗證我們的快照裡面的資料和快取資料是否一致,如果不一致,傳送SQL進行修改,

2、hibernate的get方法和load方法的區別 
1、get和load都是利用主鍵策略查詢資料, 
2、get預設不使用懶載入機制,load預設要使用懶載入機制,所謂的懶載入就是我們這個資料如果不使用,hibernate就不傳送SQL到資料庫查詢資料。 
3、當查詢資料庫不存在的資料的時候,get方法返回null,load方法丟擲空指標異常, 
原因是因為,load方法採用的動態代理的方式實現的,我們使用load方法的時候,hibernate會建立一個該實體的代理物件,該代理只儲存了該物件的ID,當我們訪問該實體物件其他屬性,hibernate就傳送SQL查詢資料封裝到代理物件,然後在利用代理物件返回給我們實際的資料,

3、hibernate的資料三種狀態 
hibernate把他所管理的資料劃分為三種狀態 
瞬時的(剛new出來的資料–記憶體有,資料庫沒有) 
持久的 (從資料查詢的,或者剛儲存到資料庫,session沒關閉的, 資料庫有,記憶體也有) 
遊離的 、脫管的(資料庫有,記憶體沒有) 
這裡寫圖片描述

實際上hibernate對資料劃分三種狀態,主要是為了管理我們持久的資料,在事務提交的時候,hibernate去對比處於持久狀態的資料是否發生改變,(快照區、一級快取區),當我們會話結束前,對持久狀態資料進行了修改的話,快照區的資料會跟著改變。當session提交事務的時候,如果發現快照區和一級快取的資料不一致,就會發送SQL進行修改。

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

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

5. 簡述hibernate中getCurrentSession和openSession區別 
getCurrentSession和openSession都是通過H的工廠去獲取資料庫的會話物件, 
1、getCurrentSession會綁定當前執行緒,而openSession不會,因為我們把hibernate交給我們的spring來管理之後,我們是有事務配置,這個有事務的執行緒就會綁定當前的工廠裡面的每一個session,而openSession是建立一個新session。 
2、getCurrentSession事務是有spring來控制的,而openSession需要我們手動開啟和手動提交事務, 
3、getCurrentSession是不需要我們手動關閉的,因為工廠會自己管理,而openSession需要我們手動關閉。 
4、而getCurrentSession需要我們手動設定 繫結事務的機制,有三種設定方式,jdbc本地的Thread、JTA、第三種是spring提供的事務管理機制org.springframework.orm.hibernate4.SpringSessionContext,而且srping預設使用該種事務管理機制,

6. 簡述hibernate的樂觀鎖和悲觀鎖

   hibernate在管理我們資料的時候的,永遠無法避免一個問題,那就是併發,
  • 1
  • 2

併發指的是多個執行緒同時訪問同一個資源,而併發會存在很多問題, 
同步指的是多個執行緒訪問同一資源的時候,當一個執行緒對該資源的操作完成了以後,才交給下一個執行緒進行操作,有點像排隊 
非同步指的是多個執行緒訪問同一資源的時候,所有的執行緒一起訪問這個資源,不需要等待其他執行緒訪問完成,也可以進行訪問和操作。有點像擠公交車 
而我們hiberante在併發的時候會存在如下問題: 
1、丟失資料更新 
這裡寫圖片描述
如上圖我們可以看出,執行緒1和執行緒2都對同一條資料進行更新, 
在T8時間點執行緒2已經完成了資料的更新,在T9時間點如果執行緒1回滾age=20,那執行緒2的更新age=25就丟失, 
另外一種,如果T9時間點 我們執行緒1提交,那我們執行緒2的age=25也丟失了 
2、資料髒讀 
這裡寫圖片描述
所謂的資料髒讀,就是當併發的時候,一個執行緒進行修改,還未提交事務的時候另一個執行緒就讀取了更新後的資料,但是後面第一個執行緒回滾,更新無效,那第二個執行緒讀取到的資料就是髒資料 
3、資料虛讀或者幻讀 
這裡寫圖片描述
此處的執行緒1修改完age之後,執行緒2立馬進來修改了name,並提交事務,執行緒1在讀取我們的資料,發現被修改了2個欄位,這就是虛讀或者幻讀

4、不可重複讀 
這裡寫圖片描述
此處執行緒1先查詢age=20,執行緒2把age修改Wie30,執行緒1再次查詢的時候發現age=30,所以重複讀取兩次資料不一致,所以重複讀取出錯,

以上問題在併發中都可能存在,所以我們hiberante一定要處理執行緒併發的情況,hibernate就需要進行執行緒同步,提供的機制是利用鎖來完成,

悲觀鎖 
所謂的悲觀鎖,就是hibernate心態不好,認為每一次操作都會出現併發,所以當我們查詢資料的時候就直接把這一條資料鎖住,不讓別人操作。底層是利用的資料庫的for update來實現的,就是查詢資料的時候利用資料庫把當前查詢的資料給鎖住,不讓其他執行緒操作,實現如下:

  1. Admin admin1 = (Admin) session.get(Admin.class, 1, LockMode.UPGRADE);

  2. Admin admin2 = (Admin) session.get(Admin.class, 1, LockOptions.UPGRADE);

H4以後就不推薦使用LockMode,而使用LockOptions來實現悲觀鎖

  1. // Admin admin = (Admin) session.get(Admin.class, adminId);

  2. Admin admin1 = (Admin) session.get(Admin.class, 1, LockMode.UPGRADE);

  3. // Admin admin2 = (Admin) session.get(Admin.class, 1, LockOptions.UPGRADE);

  4. // SQLQuery q = session.createSQLQuery("select * from xx_plat_admin");

  5. // q.setLockOptions(LockOptions.UPGRADE);

  6. //

  7. // Query q1 = session.createQuery("from Admin admin");

  8. // q1.setLockMode("admin", LockMode.UPGRADE);

  9. // q1.setLockOptions(LockOptions.UPGRADE);