Hibernate最全面試題

Java3y發表於2018-03-09

Hibernate常見面試題

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

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

  1. 讀取並解析配置檔案
  2. 讀取並解析對映資訊,建立SessionFactory
  3. 開啟Sesssion
  4. 建立事務Transation
  5. 持久化操作
  6. 提交事務
  7. 關閉Session
  8. 關閉SesstionFactory

Hibernate最全面試題

使用Hibernate框架就不用我們寫很多繁瑣的SQL語句。Hibernate實現了ORM,能夠將物件對映成資料庫表,從而簡化我們的開發!

Hibernate是如何延遲載入(懶載入)?

Hibernate是如何延遲載入(懶載入)?

通過設定屬性lazy進行設定是否需要懶載入

當Hibernate在查詢資料的時候,資料並沒有存在與記憶體中,當程式真正對資料的操作時,物件才存在與記憶體中,就實現了延遲載入,他節省了伺服器的記憶體開銷,從而提高了伺服器的效能。

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

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

它們通過配置檔案中的many-to-one、one-to-many、many-to-many來實現類之間的關聯關係的。

hibernate的三種狀態之間如何轉換

hibernate的三種狀態之間如何轉換

Hibernate中物件的狀態:

  • 臨時/瞬時狀態
  • 持久化狀態
  • 遊離狀態

臨時/瞬時狀態

當我們直接new出來的物件就是臨時/瞬時狀態的..

  • 該物件還沒有被持久化【沒有儲存在資料庫中】
  • 不受Session的管理

這裡寫圖片描述

持久化狀態

當儲存在資料庫中的物件就是持久化狀態了

  • 當呼叫session的save/saveOrUpdate/get/load/list等方法的時候,物件就是持久化狀態
  • 在資料庫有對應的資料
  • 受Session的管理
  • 當對物件屬性進行更改的時候,會反映到資料庫中!

這裡寫圖片描述

我們來測試一下:當對物件屬性進行更改的時候,會反映到資料庫中!


        session.save(idCard);
        idCard.setIdCardName("我是測試持久化物件");

複製程式碼

這裡寫圖片描述

遊離狀態

當Session關閉了以後,持久化的物件就變成了遊離狀態了...

  • 不處於session的管理
  • 資料庫中有對應的記錄

這裡寫圖片描述

有了上面的基礎,我們就很容易說出它們之間的轉換了

  • new出來的物件是瞬時狀態->儲存到資料庫中(受Session管理)就是持久化狀態->將session close掉就是遊離狀態

比較hibernate的三種檢索策略優缺點

比較hibernate的三種檢索策略優缺點

立即檢索:

  • 優點: 對應用程式完全透明,不管物件處於持久化狀態,還是遊離狀態,應用程式都可以方便的從一個物件導航到與它關聯的物件;
  • 缺點: 1.select語句太多;2.可能會載入應用程式不需要訪問的物件白白浪費許多記憶體空間;
  • 立即檢索:lazy=false

延遲檢索:

  • 優點: 由應用程式決定需要載入哪些物件,可以避免可執行多餘的select語句,以及避免載入應用程式不需要訪問的物件。因此能提高檢索效能,並且能節省記憶體空間;
  • 缺點: 應用程式如果希望訪問遊離狀態代理類例項,必須保證他在持久化狀態時已經被初始化;
  • 延遲載入:lazy=true

迫切左外連線檢索:

  • 優點: 1對應用程式完全透明,不管物件處於持久化狀態,還是遊離狀態,應用程式都可以方便地衝一個物件導航到與它關聯的物件。2使用了外連線,select語句數目少;
  • 缺點: 1 可能會載入應用程式不需要訪問的物件,白白浪費許多記憶體空間;2複雜的資料庫表連線也會影響檢索效能;
  • 預先抓取: fetch=“join”

hibernate都支援哪些快取策略

hibernate都支援哪些快取策略

usage的屬性有4種:

  • 放入二級快取的物件,只讀(Read-only);
  • 非嚴格的讀寫(Nonstrict read/write)
  • 讀寫; 放入二級快取的物件可以讀、寫(Read/write);
  • 基於事務的策略(Transactional)

hibernate裡面的sorted collection 和ordered collection有什麼區別

hibernate裡面的sorted collection 和ordered collection有什麼區別

sorted collection

  • 是在記憶體中通過Java比較器進行排序的

ordered collection

  • 是在資料庫中通過order by進行排序的

對於比較大的資料集,為了避免在記憶體中對它們進行排序而出現 Java中的OutOfMemoryError,最好使用ordered collection。

說下Hibernate的快取機制

說下Hibernate的快取機制

一級快取:

  • Hibenate中一級快取,也叫做session的快取,它可以在session範圍內減少資料庫的訪問次數! 只在session範圍有效! Session關閉,一級快取失效!
  • 只要是持久化物件狀態的,都受Session管理,也就是說,都會在Session快取中!
  • Session的快取由hibernate維護,使用者不能操作快取內容; 如果想操作快取內容,必須通過hibernate提供的evit/clear方法操作

二級快取:

  • 二級快取是基於應用程式的快取,所有的Session都可以使用
  • Hibernate提供的二級快取有預設的實現,且是一種可插配的快取框架!如果使用者想用二級快取,只需要在hibernate.cfg.xml中配置即可; 不想用,直接移除,不影響程式碼。
  • 如果使用者覺得hibernate提供的框架框架不好用,自己可以換其他的快取框架或自己實現快取框架都可以
  • Hibernate二級快取:儲存的是常用的類

這裡寫圖片描述

Hibernate的查詢方式有幾種

Hibernate的查詢方式有幾種

  • 物件導航查詢(objectcomposition)
  • HQL查詢
    • 1、 屬性查詢
    • 2、 引數查詢、命名引數查詢
    • 3、 關聯查詢
    • 4、 分頁查詢
    • 5、 統計函式
  • Criteria 查詢
  • SQLQuery本地SQL查詢

如何優化Hibernate?

如何優化Hibernate?

  • Ø 資料庫設計調整
  • Ø HQL優化
  • Ø API的正確使用(如根據不同的業務型別選用不同的集合及查詢API)
  • Ø 主配置引數(日誌,查詢快取,fetch_size, batch_size等)
  • Ø 對映檔案優化(ID生成策略,二級快取,延遲載入,關聯優化)
  • Ø 一級快取的管理
  • Ø 針對二級快取,還有許多特有的策略

詳情可參考資料:

談談Hibernate中inverse的作用

談談Hibernate中inverse的作用

inverse屬性預設是false,就是說關係的兩端都來維護關係。

  • 比如Student和Teacher是多對多關係,用一箇中間表TeacherStudent維護。Gp)
  • 如果Student這邊inverse=”true”, 那麼關係由另一端Teacher維護,就是說當插入Student時,不會操作TeacherStudent表(中間表)。只有Teacher插入或刪除時才會觸發對中間表的操作。所以兩邊都inverse=”true”是不對的,會導致任何操作都不觸發對中間表的影響;當兩邊都inverse=”false”或預設時,會導致在中間表中插入兩次關係。

如果表之間的關聯關係是“一對多”的話,那麼inverse只能在“一”的一方來配置!

詳情可參考:

JDBC hibernate 和 ibatis 的區別

JDBC hibernate 和 ibatis 的區別

jdbc:手動

  • 手動寫sql
  • delete、insert、update要將物件的值一個一個取出傳到sql中,不能直接傳入一個物件。
  • select:返回的是一個resultset,要從ResultSet中一行一行、一個欄位一個欄位的取出,然後封裝到一個物件中,不直接返回一個物件。

ibatis的特點:半自動化

  • sql要手動寫
  • delete、insert、update:直接傳入一個物件
  • select:直接返回一個物件

hibernate:全自動

  • 不寫sql,自動封裝
  • delete、insert、update:直接傳入一個物件
  • select:直接返回一個物件

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

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

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

詳情可參考:

什麼是SessionFactory,她是執行緒安全麼

什麼是SessionFactory,她是執行緒安全麼

SessionFactory 是Hibrenate單例資料儲存和執行緒安全的,以至於可以多執行緒同時訪問。一個SessionFactory 在啟動的時候只能建立一次。SessionFactory應該包裝各種單例以至於它能很簡單的在一個應用程式碼中儲存.

get和load區別

get和load區別

  • get()立即查詢

這裡寫圖片描述

  • load()懶載入

這裡寫圖片描述

  • 1)get如果沒有找到會返回null, load如果沒有找到會丟擲異常。
  • 2)get會先查一級快取, 再查二級快取,然後查資料庫;load會先查一級快取,如果沒有找到,就建立代理物件, 等需要的時候去查詢二級快取和資料庫。

merge的含義:

merge的含義:

  • 如果session中存在相同持久化標識(identifier)的例項,用使用者給出的物件的狀態覆蓋舊有的持久例項
  • 如果session沒有相應的持久例項,則嘗試從資料庫中載入,或建立新的持久化例項,最後返回該持久例項
  • 使用者給出的這個物件沒有被關聯到session上,它依舊是脫管的

詳情可參考:

persist和save的區別

persist和save的區別

  • persist不保證立即執行,可能要等到flush;
  • persist不更新快取;
  • save, 把一個瞬態的例項持久化識別符號,及時的產生,它要返回識別符號,所以它會立即執行Sql insert
  • 使用 save() 方法儲存持久化物件時,該方法返回該持久化物件的標識屬性值(即對應記錄的主鍵值);
  • 使用 persist() 方法來儲存持久化物件時,該方法沒有任何返回值

參考資料:

主鍵生成 策略有哪些

主鍵生成 策略有哪些

主鍵的自動生成策略

  • identity 自增長(mysql,db2)
  • sequence 自增長(序列), oracle中自增長是以序列方法實現**
  • native 自增長【會根據底層資料庫自增長的方式選擇identity或sequence】
    • 如果是mysql資料庫, 採用的自增長方式是identity
    • 如果是oracle資料庫, 使用sequence序列的方式實現自增長
  • increment 自增長(會有併發訪問的問題,一般在伺服器叢集環境使用會存在問題。)

指定主鍵生成策略為手動指定主鍵的值

  • assigned

指定主鍵生成策略為UUID生成的值

  • uuid

foreign(外來鍵的方式)

簡述hibernate中getCurrentSession和openSession區別

簡述hibernate中getCurrentSession和openSession區別

  • 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預設使用該種事務管理機制

Hibernate中的命名SQL查詢指的是什麼?

Hibernate中的命名SQL查詢指的是什麼?

  • 命名查詢指的是用<sql-query>標籤在影射文件中定義的SQL查詢,可以通過使用Session.getNamedQuery()方法對它進行呼叫。命名查詢使你可以使用你所指定的一個名字拿到某個特定的查詢。
  • Hibernate中的命名查詢可以使用註解來定義,也可以使用我前面提到的xml影射問句來定義。在Hibernate中,@NameQuery用來定義單個的命名查詢,@NameQueries用來定義多個命名查詢。

為什麼在Hibernate的實體類中要提供一個無引數的構造器這一點非常重要?

為什麼在Hibernate的實體類中要提供一個無引數的構造器這一點非常重要?

每個Hibernate實體類必須包含一個 無引數的構造器, 這是因為Hibernate框架要使用Reflection API,通過呼叫Class.newInstance()來建立這些實體類的例項。如果在實體類中找不到無引數的構造器,這個方法就會丟擲一個InstantiationException異常。

可不可以將Hibernate的實體類定義為final類?

可不可以將Hibernate的實體類定義為final類?

可以將Hibernate的實體類定義為final類,但這種做法並不好。因為Hibernate會使用代理模式在延遲關聯的情況下提高效能,如果你把實體類定義成final類之後,因為Java不允許對final類進行擴充套件,所以Hibernate就無法再使用代理了, 如此一來就限制了使用可以提升效能的手段。

最後

參考資料:


如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y

相關文章