Hibernate面試問題集錦: 概述

Q.怎麼配置Hibernate?

A.Configuration類使用配置hibernate.cfg.xml(或者hibernate.properties)以及映射文件*.hbm.xml來創建(例如,配置和引導hibernate)SessionFactory,然後SessionFactory創建Session的實例。Session的實例是持久層服務對外提供的主要接口。

hibernate.cfg.xml(或者你也可以使用hibernate.properties):這兩個文件都是用來配置hibernate服務(數據庫連接的驅動類,連接URL,用戶名,密碼,方言等)。如果這兩個文件同時存在於classpath裏的話,那麼hibernate.cfg.xml會覆蓋hibernate.properties文件裏的配置。

映射文件(*.hbm.xml):這些文件都是用來對持久層對象和關係數據庫進行映射的。最好的方式是對每個對象都使用單獨的映射文件(例如一個類一個文件),因爲如果在一個文件裏存放大量的持久層對象,那麼這個文件就變得非常難管理和維護。約定的命名方式是映射文件名和持久層類名(POJO)保持一致。例如,Account.class的映射文件名爲Account.hbm.xml。或者,你也可以在類文件的代碼里加上hibernate的註解,從而不需要使用配置文件。

Q.什麼是SessionFactory?它是線程安全的嗎?

A.SessionFactory對應Hibernate的一個數據存儲的概念,並且它是線程安全的,可以被多個線程併發訪問,也可以請求session和單個數據庫的不可變編譯過的映射的緩存。SessionFactory一般只會在啓動的時候構建。對於應用代碼,最好對SessionFactory通過單例的模式進行封裝以便於訪問。

1
SessionFactory sessionFactory = newConfiguration( ).configure( ).buildSessionfactory( );

Q.Session是什麼?兩個線程能共享同一個session嗎?

A.Session是一個輕量級非線程安全的對象(線程間不能共享session),它表示與數據庫進行交互的一個工作單元。Session是被SessionFactory創建的,在任務完成之後它會被關閉。Session是持久層服務對外提供的主要接口。Session會延遲獲取數據庫連接(也就是在需要的時候纔會獲取)。爲了避免創建太多的session,可以使用ThreadLocal來取得當前的session,無論你調用多少次currentSession()方法,返回的都是同一個session。下面是示例代碼:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
publicclass HibernateUtil {
 
    publicstatic final ThreadLocal local = newThreadLocal();
 
    publicstatic Session currentSession() throwsHibernateException {
 
         Session session = (Session) local.get();
 
         //open a new session if this thread has no session
 
        if(session == null) {
 
            session = sessionFactory.openSession();
 
            local.set(session);
 
       }
 
        returnsession;
 
    }
 
}

 

有一點很重要的就是如果一個工作單元完成了,你需要關閉你的session。注意:保持你的Hibernate Session API簡單易用。比較常見的場景是,hibernate會和Spring框架一起使用,通過HibernateTemplate來整合。

 

Q.解釋hibernate對象的狀態?解釋hibernate對象的生命週期?

A.持久層(persistent )對象和集合都是存活時間短暫的單線程對象,它們保存持久層的狀態。這些對象的狀態會根據你的刷新規則(例如,一旦有setXXX()方法被調用了就自動刷新,或者有數據項從集合、列表等刪除時就刷新,你也可以通過session.flush()和transaction.commit()這兩個函數調用來定義你自己的同步策略)來與數據庫保持同步。如果你從一個持久層的集合(例如Set)裏刪除一項,那麼它要麼被立即從數據庫裏刪除,或者當flush()或則commit()方法被調用時刪除,具體的表現取決於你的刷新策略。它們都是普通的Java對象(POJO,Plain Old Java Object),只不過當前關聯了一個session。一旦關聯的session被關閉,持久層對象就成爲了遊離對象(detached object),這時候你就可以在隨便使用它們了,就像是用在業務層,持久層等其他應用層面的數據傳輸對象一樣。

遊離(detached )對象和集合都是和session相關聯的持久層對象的實例,只不過它們現在沒有和session進行關聯。這種對象可以被隨便使用,它不會對你的數據庫有任何影響。遊離對象後面也可以通過調用類似session.update(),session.saveOrUpdate()等方法來依附到其他的session上,然後再次成爲持久層對象。

瞬態(transient)對象和集合是從來沒有和session相關聯的持久層對象的實例。這些對象可以自由使用,並且不會對你的數據庫造成任何影響。當通過session.save(),session.persist()方法來使得瞬態對象和一個session進行關聯時,瞬態對象就成爲了持久層對象。


 

Q.使用遊離對象(detached object)有什麼好處呢?

優點:

  • 當因用戶的思考時間而需要使用長事務時,最好的方式是把長事務分成一個或者多個事務。你可以使用來自於第一個事務的遊離對象來承載持久層的所有數據。這些遊離的對象在事務外被修改,然後可以通過另一個session來加入到新的事務裏。

 

缺點:

  • 一般來說,使用遊離對象的方式是比較笨重的,並且如果可以的話最好不要使得session變得比較混亂。最好的方式是丟棄這些對象,然後在後面的請求裏重新獲取新的對象。這個方式不僅更具有移植性,而且更加高效——因爲這些對象會留在Hibernate的緩存裏。
  • 同時,從純粹的富領域驅動的方式來看,比較推薦的方式是使用DTO(DataTransferObject)和DO(DomainObject)來保持Service層和UI層之間的分離。

 

Q.什麼時候對象會變成遊離的?

A.

1
2
3
4
5
Session session1 = sessionFactory.openSession();
 
Car myCar = session1.get(Car.class, carId);     //“myCar”這個時候是一個持久層對象
 
session1.close();      //當session關閉時,“myCar”就成爲了遊離對象

 

現在你可以把“myCar”對象傳到一直傳到表示層裏。它可以被修改並且對數據庫表沒有影響。

1
myCar.setColor(“Red”);//對數據庫沒有影響

當你需要把修改持久化到數據庫時,可以把遊離對象加入到另外一個session裏,示例如下:

 

1
2
3
4
5
6
7
8
9
Session session2 = sessionFactory.openSession();
 
Transaction tx = session2.beginTransaction();
 
session2.update(myCar);             //遊離對象”myCar“加入到session
 
tx.commit();                     //修改被同步到數據庫
 
session2.close()

 

Q.Hibernate怎麼區別瞬態對象(例如,剛實例化的)和遊離對象?

A.

  • 如果存在”version”這個屬性的話,Hibernate會使用它來進行區別。
  • 如果不存在的話,會使用標識符值(identifier value)來進行判斷。沒有標識符表示這是一個新對象。這隻適合Hibernate管理代理主鍵(surrogate key)的場景,不適合於使用自然主鍵(natural key)或者assigned代理主鍵(沒有被Hibernate管理)的場景。
  • 通過InterceptorisUnsaved()來實現你自己的策略。

 

注意:當你重新關聯遊離的對象時,你必須保證依賴的對象也都被重新進行關聯。

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