Hibernate面試題集錦(附解析)

本文只是對原文進行了完善和補充。
一,選擇題:
(1)一般情況下,關係數據模型與對象模型之間有哪些匹配關係(多選)
A)表對應類B)記錄對應對象C)表的字段對應類的屬性D)表之間的參考關係對應類之間的依賴關係
解析:
答案:abc
a.表必須對應類(可以名字不一樣,但不提倡那麼幹)
b......
c.要是查詢出來的數據爲我們所用,並且得到好的封裝
d.在做many-to-many對應關係是就算沒有外鍵關係與之對應,也也可以操作
 
(2)以下關於SessionFactory的說法哪些正確?(多選)
A)對於每個數據庫事務,應該創建一個SessionFactory對象
B)一個SessionFactory對象對應一個數據庫存儲源。
C)SessionFactory是重量級的對象,不應該隨意創建。如果系統中只有一個數據庫存儲源,只需要創建一個。
D)SessionFactory的load()方法用於加載持久化對象
解析:
答案:bc
sessionFactory是一個重量級的對象,因此創建是會耗費大量資源。一個SessionFactory對應一個數據庫存儲源。
 
(3)Customer類中有一個Set類型的orders屬性,用來存放Order訂單對象,在Customer.hbm.xml文件中,用哪個元素映射orders屬性?  

A)<set> B)<one-to-many> C)<many-to-one> D)<property>

解析:
答案:a
學過hibernate的都知道

(4)元素有一個cascade屬性,如果希望Hibernate級聯保存集合中的對象,casecade屬性應該取什麼值?(單選)
A)noneB)saveC)deleteD)save-update
解析:
答案:d

cascade屬性值描述

none在保存、更新或者刪除對象時,忽略其他關聯的對象,它是級聯的默認值
save-update當通過Session的Save()、Update()以及SaveOrUpdate()方法來保存、更新對象時,級聯保存關聯的臨時對象,並更新關聯的遊離對象。
delete當通過Session的Delete()方法刪除當前對象時,同時會刪除關聯的所有對象。
all包含save-update以及delete的行爲,此外對當前對象進行Evict()或者Lock()方法時會對關聯的對象進行同樣的操作。
delete-orphan刪除所有和當前對象解除關聯關係的對象。
all-delete-orphan包含all和delete-orphan的行爲。
 
(5)以下哪些屬於Session的方法?
A)load()B)save()C)delete()D)update()E)open()F)close()
解析:
答案:ABCDF
 
(6)以下程序的打印結果是什麼?(單選)
 
tx = session.beginTransaction();  
Customer c1=(Customer)session.load(Customer.class,new Long(1));  
Customer c2=(Customer)session.load(Customer.class,new Long(1));  
System.out.println(c1==c2);  
tx.commit();  
session.close(); 
A)運行出錯,拋出異常B)打印falseC)打印true
解析:
答案:C
==比較的是兩個基本數據類型變量的值和應用類型的地址
equals比較的是兩個對象是否是同一對象的應用
 
 
(7)以下程序代碼對Customer的name屬性修改了兩次:
tx = session.beginTransaction();  
Customer customer=(Customer)session.load(Customer.class,  
new Long(1));  
customer.setName(\"Jack\");  
customer.setName(\"Mike\");  
tx.commit(); 
執行以上程序,Hibernate需要向數據庫提交幾條update語句?(單選)
A)0 B)1 C)2 D)3
解析:
答案:B
 
(8)在持久化層,對象分爲哪些狀態?(多選)
A)臨時狀態B)獨立狀態C)遊離狀態D)持久化狀態
解析:
答案:ACD
在Hibernate中,對象有三種狀態:臨時狀態、持久狀態和遊離狀態。 

臨時狀態: 當new一個實體對象後,這個對象處於臨時狀態 ,即這個對象只是一個保存臨時數據的內存區域,如果沒有變量引用這個對象,則會被jre垃圾回收機制回收。這個對象所保存的數據與數據庫沒有任何關係,除非通過Session的save或者SaveOrUpdate把臨時對象與數據庫關聯,並把數據插入或者更新到數據庫,這個對象才轉換爲持久對象。 
例如:Emp e=new Emp();    //創建臨時對象 
          e.setEmpno((long) 8888); 
          e.setEName("mike"); 
          ... 
          EmpDAO d=new EmpDAO(); 
          d.save(e);      //持久化 
          ...

持久狀態:持久化對象的實例在數據庫中有對應的記錄,並擁有一個持久化表示(ID)。對持久化對象進行delete操作後,數據庫中對應的記錄將被刪除,那麼持久化對象與數據庫記錄不再存在對應關係,持久化對象變成臨時狀態。
    持久化對象被修改變更後,不會馬上同步到數據庫,知道數據庫事務提交。在同步之前,持久化對象是髒的(Dirty)。
例如:
          Emp e=new Emp(); //創建了臨時的對象
          EmpDAO edao= new empDAO();
          e=edao.findbyEmpno((long) 7786);    //使對象與數據庫記錄對應,從而持久化
          e.setEname("新的名字");                     //修改了持久化對象,使之處於 Dirty
          ......
          edao.saveorupdate(e);                      //保存,但是仍然 Dirty
          tran.commit();                                     //提交,實現與數據庫同步,不再Dirty
          ......

遊離狀態:當Session進行了Close、Clear或者evict後,持久化對象雖然擁有持久化標識符和與數據庫對應記錄一致的值,但是因爲會話已經消失,對象不在持久化管理之內,所以處於遊離狀態(也叫:脫管狀態)。遊離狀態的對象與臨時狀態對象是十分相似的,只是它還含有持久化標識。

其中,持久化狀態的對象,簡稱爲:PO
而臨時狀態和遊離狀態的對象,簡稱爲: VO

 

(9)對於以下程序,Customer對象在第幾行變爲持久化狀態?(單選)
Customer customer=new Customer(); //line1  
customer.setName(\"Tom\"); //line2  
Session session1=sessionFactory.openSession(); //line3  
Transaction tx1 = session1.beginTransaction(); //line4  
session1.save(customer); //line4  
tx1.commit(); //line5  
session1.close(); //line6 
A) line1 B)line2 C)line3 D)line4 E)line5 F)line6
解析:
答案:D
原因同8題所述
 
 
(10)對於以下程序,Customer對象在第幾行變爲遊離狀態?(單選)
Customer customer=new Customer(); //line1  
customer.setName(\"Tom\"); //line2  
Session session1=sessionFactory.openSession(); //line3  
Transaction tx1 = session1.beginTransaction(); //line4  
session1.save(customer); //line4  
tx1.commit(); //line5  
session1.close(); //line6 
A) line1 B)line2 C)line3 D)line4 E)line5 F)line6
解析:
答案:F
原因同8題
 
(11)以下哪一種檢索策略利用了外連結查詢?(單選)
A)立即檢索 B)延遲檢索 C)迫切左外連結檢索
解析:
答案:C
1、立即檢索: 
優點:
對應用程序完全透明,不管對象處於持久化狀態,還是遊離狀態,應用程序都可以方便地從一個對象導航到與它關聯的對象。
缺點:
[1]select語句數目多
[2]可能會加載應用程序不需要訪問的對象,浪費時間和內存空間
優先考慮使用的場合:
[1]類級別
[2]應用程序需要立即訪問的對象
[3]使用了二級緩存
2、延遲檢索:
優點:
由應用程序決定需要加載哪些對象,可以避免執行多餘的select語句,以及避免加載應用程序不需要訪問的對象。因此能提高檢索性能,並且節省內存空間
缺點:
應用程序如果需要訪問遊離狀態的代理類實例,必須保證它在持久化狀態時已經被初始化。
優先考慮使用的場合:
[1]一對多或者多對多關聯
[2]應用程序不需要立即訪問或者根本不訪問的對象
3、迫切左外連接檢索:
優點:
[1]對應用程序完全透明,不管對象處於之久化狀態還是遊離狀態,應用程序都可以方便的從一個對象 導航到另一個與它關聯的對象 
[2]使用了外連接, select語句數目少(使用連接查詢)
缺點:
[1]可能會加載應用程序不需要訪問的對象,浪費內存空間
[2]複雜的數據表連接會影響檢索性能
優先考慮使用的場合:
[1]多對一或者一對一關聯
[2]應用程序需要立即訪問的對象
[3]數據庫系統具有良好的表連接性能


(12)假設對Customer類的orders集合採用延遲檢索策略,編譯或運行以下程序,會出現什麼情況(單選)
Session session=sessionFactory.openSession();  
tx = session.beginTransaction();  
Customer customer=(Customer)session.get(Customer.class,new Long(1));  
tx.commit();  
session.close();  
Iterator orderIterator=customer.getOrders().iterator(); 
A)編譯出錯 B)編譯通過,並正常運行 C)編譯通過,但運行時拋出異常
解析:
答案:C

(13)關於HQL與SQL,以下哪些說法正確?(多選)
A)HQL與SQL沒什麼差別B)HQL面向對象,而SQL操縱關係數據庫C)在HQL與SQL中,都包含select,insert,update,delete語句D)HQL僅用於查詢數據,不支持insert,update和delete語句
解析:
答案:C
HQL(Hibernate QUERY LANGUAGE)只能查詢語句
 
 
 
(14)事務隔離級別是由誰實現的?(單選)
A)Java應用程序 B)Hibernate C)數據庫系統 D)JDBC驅動程序
解析:
答案:C
地球人都知道

(15)悲觀鎖與樂觀鎖,哪個具有較好的併發性能?(單選)
A)悲觀鎖 B)樂觀鎖
解析:
答案:B
1.悲觀鎖

它指的是對數據被外界修改持保守態度。假定任何時刻存取數據時,都可能有另一個客戶也正在存取同一筆數據,爲了保持數據被操作的一致性,於是對數據採取了數據庫層次的鎖定狀態,依靠數據庫提供的鎖機制來實現。  
基於jdbc實現的數據庫加鎖如下:  
select * from account where name="Erica" for update

在更新的過程中,數據庫處於加鎖狀態,任何其他的針對本條數據的操作都將被延遲。本次事務提交後解鎖。  
而hibernate悲觀鎖的具體實現如下:  
String sql="查詢語句";  
Query query=session.createQuery(sql);  
query.setLockMode("對象",LockModel.UPGRADE);

說到這裏,就提到了hibernate的加鎖模式:

LockMode.NONE:無鎖機制。  
LockMode.WRITE:Hibernate在Insert和Update記錄的時候會自動獲取。  
LockMode.READ:Hibernate在讀取記錄的時候會自動獲取。

這三種加鎖模式是供hibernate內部使用的,與數據庫加鎖無關:

LockMode.UPGRADE:利用數據庫的for update字句加鎖。

在這裏我們要注意的是:只有在查詢開始之前(也就是hiernate生成sql語句之前)加鎖,纔會真正通過數據庫的鎖機制加鎖處理。否則,數據已經通過不包含for updata子句的sql語句加載進來,所謂的數據庫加鎖也就無從談起。  
但是,從系統的性能上來考慮,對於單機或小系統而言,這並不成問題,然而如果是在網絡上的系統,同時間會有許多聯機,假設有數以百計或上千甚至更多的併發訪問出現,我們該怎麼辦?如果等到數據庫解鎖我們再進行下面的操作,我們浪費的資源是多少?--這也就導致了樂觀鎖的產生。

2.樂觀鎖

樂觀鎖定(optimistic locking)則樂觀的認爲資料的存取很少發生同時存取的問題,因而不作數據庫層次上的鎖定,爲了維護正確的數據,樂觀鎖定採用應用程序上的邏輯實現版本控制的方法。

例如若有兩個客戶端,A客戶先讀取了賬戶餘額100元,之後B客戶也讀取了賬戶餘額100元的數據,A客戶提取了50元,對數據庫作了變更,此時數據庫中的餘額爲50元,B客戶也要提取30元,根據其所取得的資料,100-30將爲70餘額,若此時再對數據庫進行變更,最後的餘額就會不正確。

在不實行悲觀鎖定策略的情況下,數據不一致的情況一但發生,有幾個解決的方法,一種是先更新爲主,一種是後更新的爲主,比較複雜的就是檢查發生變動的數據來實現,或是檢查所有屬性來實現樂觀鎖定。

Hibernate 中透過版本號檢查來實現後更新爲主,這也是Hibernate所推薦的方式,在數據庫中加入一個VERSON欄記錄,在讀取數據時連同版本號一同讀取,並在更新數據時遞增版本號,然後比對版本號與數據庫中的版本號,如果大於數據庫中的版本號則予以更新,否則就回報錯誤。

以剛纔的例子,A客戶讀取賬戶餘額1000元,並連帶讀取版本號爲5的話,B客戶此時也讀取賬號餘額1000元,版本號也爲5,A客戶在領款後賬戶餘額爲500,此時將版本號加1,版本號目前爲6,而數據庫中版本號爲5,所以予以更新,更新數據庫後,數據庫此時餘額爲500,版本號爲6,B客戶領款後要變更數據庫,其版本號爲5,但是數據庫的版本號爲6,此時不予更新,B客戶數據重新讀取數據庫中新的數據並重新進行業務流程才變更數據庫。

以Hibernate實現版本號控制鎖定的話,我們的對象中增加一個version屬性,例如:  
view plaincopy to clipboardprint?
public class Account {     
private int version;     
....     
public void setVersion(int version) {     
this.version = version;     
}     
public int getVersion() {     
return version;     
}     
....     
}    
public class Account {  
private int version;  
....  
public void setVersion(int version) {  
this.version = version;  
}  
public int getVersion() {  
return version;  
}  
....  


二,簡答題

 

Hibernate工作原理及爲什麼要用?

答:

原理:

1.讀取並解析配置文件

2.讀取並解析映射信息,通過SessionFactory創建Session

3.打開Sesssion

4.創建事務Transation

5.持久化操作

6.提交事務

7.關閉Session

爲什麼要用:

1. 對JDBC訪問數據庫的代碼做了封裝,大大簡化了數據訪問層繁瑣的重複性代碼。

2. Hibernate是一個基於JDBC的主流持久化框架,是一個優秀的ORM實現。他很大程度的簡化DAO層的編碼工作

3. hibernate使用Java反射機制,而不是字節碼增強程序來實現透明性。

4. hibernate的性能非常好,因爲它是個輕量級框架。映射的靈活性很出色。它支持各種關係數據庫,從一對一到多對多的各種複雜關係。



2. Hibernate是如何延遲加載?
答:

 

1. Hibernate2延遲加載實現:a)實體對象 b)集合(Collection)

2. Hibernate3 提供了屬性的延遲加載功能

當Hibernate在查詢數據的時候,數據並沒有存在與內存中,當程序真正對數據的操作時,對象才存在與內存中,就實現了延遲加載,他節省了服務器的內存開銷,從而提高了服務器的性能。

 

 

3.hibernate 進行多表查詢每個表中各取幾個字段,也就是說查詢出來的結果集沒有一個實體類與之對應如何解決

 

可以將查詢返回一個DynaBean比如

List<DynaBean>list=statement.executeSQLQuery("select a.aa,b.bb from a,b");

for(DynaBean db:list){

          String a1= (String)db.get("aa");

          Stringb1= (String)db.get("bb");

}

Or

List list=query.list();

Iterator it=list.itreator();

While(it.hasNext()){

        Object[]obj=(Object[])it.next();

        Stringal=(String)obj[0];

}


 

4.Hibernate中怎樣實現類之間的關係?(如:一對多、多對多的關係)

答:

類與類之間的關係主要體現在表與表之間的關係進行操作,它們都是對對象進行操作,我們程序中把所有的表與類都映射在一起,它們通過配置文件中的many-to-one、one-to-many、many-to-many

 

 

 

5. 說下Hibernate的緩存機制

答:

hibernate中存在兩種緩存,即內置緩存和外只緩存。

1. 內部緩存存在Hibernate中又叫一級緩存,屬於應用事物級緩存

2. 二級緩存:

a) 應用及緩存

b) 分佈式緩存

條件:數據不會被第三方修改、數據大小在可接受範圍、數據更新頻率低、同一數據被系統頻繁使用、非 關鍵數據

c) 第三方緩存的實現

 

 

 

6. Hibernate的查詢方式

Sql、Criteria,object comptosition

Hql:

1、 屬性查詢

2、 參數查詢、命名參數查詢

3、 關聯查詢

4、 分頁查詢

5、 統計函數


7.hibernate 中的 update()  saveOrUpdate() 的區別, session  load()  get() 的區別。 

答:

 

Update 更新的是已有的數據,如果沒有則會報錯。 SaveOrUpdate 則可以將數據庫中沒有數據進行保存,有的數據進行修改

Load  get 都是查詢數據對象。 Load 首先會從緩存中加載,如果緩存中沒有該數據,則去數據庫中查找, get 會直接去數據庫加載。當數據的查詢波動比較小時,可以使用 load 來優化數據操作,反之則會帶來更大的負擔

從這個可以將一些關於iterate和list()來優化考官對自己的認可之類的



 

 

8.Session清理緩存的三種模式

清理緩存的模式           

 Session查詢方法                 

 Session的Commit方法                 

 Session的Flush方法                 

 

 

9. Hibernate的主鍵生成機制 

答:

在項目中,通常使用UUID(Universally Unique Identifier 唯一標示符)作爲主鍵.

常用的組建有:

 

 

1) Assigned 

     主鍵由外部程序負責生成,無需Hibernate參與。

2) hilo 
     通過hi/lo 算法實現的主鍵生成機制,需要額外的數據庫表保存主鍵生成歷史狀態。

3) native       由Hibernate根據底層數據庫自行判斷採用identity、hilo、sequence其中一種作爲主鍵生成方式。
4) increment 

     主鍵按數值順序遞增。此方式的實現機制爲在當前應用實例中維持一個變量,以保存着當前的最大值,之後每次需要生成主鍵的時候將此值加1作爲主鍵。 
  這種方式可能產生的問題是:如果當前有多個實例訪問同一個數據庫,那麼由於各個實例各自維護主鍵狀態,不同實例可能生成同樣的主鍵,從而造成主鍵重複異常。因此,如果同一數據庫有多個實例訪問,此方式必須避免使用。

5) identity 
      採用數據庫提供的主鍵生成機制。如DB2、SQL Server、MySQL中的主鍵生成機制。

6) sequence 
      採用數據庫提供的sequence 機制生成主鍵。如Oralce 中的Sequence。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章