Hibernate常見面試題


1、什么是Hibernate的並發機制?怎么去處理並發問題?

2、update和saveOrUpdate的區別?

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

1、什么是Hibernate的並發機制?怎么去處理並發問題?

Hibernate並發機制:

a、Hibernate的Session對象是非線程安全的,對於單個請求,單個會話,單個的工作單元(即單個事務,單個線程),它通常只使用一次, 然后就丟棄。

如果一個Session 實例允許共享的話,那些支持並發運行的,例如Http request,session beans將會導致出現資源爭用。

如果在Http Session中有hibernate的Session的話,就可能會出現同步訪問Http Session。只要用戶足夠快的點擊瀏覽器的“刷新”, 就會導致兩個並發運行的線程使用同一個Session。

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

解決方案:設置事務隔離級別。
Serializable:串行化。隔離級別最高
Repeatable Read:可重復讀
Read Committed:已提交數據讀
Read Uncommitted:未提交數據讀。隔離級別最差
設置鎖:樂觀鎖和悲觀鎖。
樂觀鎖:使用版本號或時間戳來檢測更新丟失,在的映射中設置 optimistic-lock=”all”可以在沒有版本或者時間戳屬性映射的情況下實現 版本檢查,此時Hibernate將比較一行記錄的每個字段的狀態 行級悲觀鎖:Hibernate總是使用數據庫的鎖定機制,從不在內存中鎖定對象!只要為JDBC連接指定一下隔 離級別,然后讓數據庫去搞定一切就夠了。類LockMode 定義了Hibernate所需的不同的鎖定級別:LockMode.UPGRADE,LockMode.UPGRADE_NOWAIT,LockMode.READ;

2、update和saveOrUpdate的區別?

update()和saveOrUpdate()是用來對跨Session的PO進行狀態管理的。
update()方法操作的對象必須是持久化了的對象。也就是說,如果此對象在數據庫中不存在的話,就不能使用update()方法。
saveOrUpdate()方法操作的對象既可以使持久化了的,也可以使沒有持久化的對象。如果是持久化了的對象調用saveOrUpdate()則會 更新數據庫中的對象;如果是未持久化的對象使用此方法,則save到數據庫中。

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

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

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

1立即檢索;
優點: 對應用程序完全透明,不管對象處於持久化狀態,還是游離狀態,應用程序都可以方便的從一個對象導航到與它關聯的對象;
缺點: 1.select語句太多;2.可能會加載應用程序不需要訪問的對象白白浪費許多內存空間;
2延遲檢索:
優點: 由應用程序決定需要加載哪些對象,可以避免可執行多余的select語句,以及避免加載應用程序不需要訪問的對象。因此能提高檢索性能,並且能節省內存空間;
缺點: 應用程序如果希望訪問游離狀態代理類實例,必須保證他在持久化狀態時已經被初始化;
3 迫切左外連接檢索
優點: 1對應用程序完全透明,不管對象處於持久化狀態,還是游離狀態,應用程序都可以方便地沖一個對象導航到與它關聯的對象。2使用了外連接,select語句數目少;
缺點: 1 可能會加載應用程序不需要訪問的對象,白白浪費許多內存空間;2復雜的數據庫表連接也會影響檢索性能;

詳見:https://www.cnblogs.com/lukelook/p/11186768.html

5、如何在控制台看到hibernate生成並執行的sql

在定義數據庫和數據庫屬性的文件applicationConfig.xml里面,把hibernate.show_sql 設置為true
這樣生成的SQL就會在控制台出現了
注意:這樣做會加重系統的負擔,不利於性能調優

6、hibernate都支持哪些緩存策略

Read-only: 這種策略適用於那些頻繁讀取卻不會更新的數據,這是目前為止最簡單和最有效的緩存策略
* Read/write:這種策略適用於需要被更新的數據,比read-only更耗費資源,在非JTA環境下,每個事務需要在session.close和session.disconnect()被調用
* Nonstrict read/write: 這種策略不保障兩個同時進行的事務會修改同一塊數據,這種策略適用於那些經常讀取但是極少更新的數據
* Transactional: 這種策略是完全事務化得緩存策略,可以用在JTA環境下

7、hibernate里面的sorted collection 和ordered collection有什么區別

sorted collection是在內存中通過Java比較器進行排序的
ordered collection是在數據庫中通過order by進行排序的

8、Hibernate工作原理及為什么要用?

1.讀取並解析配置文件
2.讀取並解析映射信息,創建SessionFactory
3.打開Sesssion
4.創建事務Transation
5.持久化操作
6.提交事務
7.關閉Session
8.關閉SesstionFactory

為什么要用:
1. 對JDBC訪問數據庫的代碼做了封裝,大大簡化了數據訪問層繁瑣的重復性代碼。

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

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

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

10、Hibernate是如何延遲加載?

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

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

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

12、說下Hibernate的緩存機制

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

二級緩存:
a) 應用及緩存
b) 分布式緩存
條件:數據不會被第三方修改、數據大小在可接受范圍、數據更新頻率低、同一數據被系統頻繁使用、非關鍵數據
c) 第三方緩存的實現

13、Hibernate的查詢方式

Sql、Criteria,objectcomposition
Hql:
1、 屬性查詢
2、 參數查詢、命名參數查詢
3、 關聯查詢
4、 分頁查詢
5、 統計函數

14、如何優化Hibernate?

1.使用雙向一對多關聯,不使用單向一對多
2.靈活使用單向一對多關聯
3.不用一對一,用多對一取代
4.配置對象緩存,不使用集合緩存
5.一對多集合使用Bag,多對多集合使用Set
6. 繼承類使用顯式多態
7. 表字段要少,表關聯不要怕多,有二級緩存撐腰

 

答:這個問題應當挑自己使用過的優化策略回答,常用的有:
① 制定合理的緩存策略(二級緩存、查詢緩存)。
② 采用合理的Session管理機制。
③ 盡量使用延遲加載特性。
④ 設定合理的批處理參數。
⑤ 如果可以,選用UUID作為主鍵生成器。
⑥ 如果可以,選用基於版本號的樂觀鎖替代悲觀鎖。
⑦ 在開發過程中, 開啟hibernate.show_sql選項查看生成的SQL,從而了解底層的狀況;開發完成后關閉此選項。
⑧ 考慮數據庫本身的優化,合理的索引、恰當的數據分區策略等都會對持久層的性能帶來可觀的提升,但這些需要專業的DBA(數據庫管理員)提供支持。

15、Hibernate有哪幾種查詢數據的方式

3種:hql、條件查詢QBC(QueryBy Criteria)、原生sql (通過createSQLQuery建立)

6、談談Hibernate中inverse的作用

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

17、Detached Object(游離對象)有什么好處

Detached Object(游離對象)可以傳遞到任何層直到表現層而不是用任何DTO(DataTransfer Objects). 然后你還可以重新把游離對象賦給另外一個Session.

18、JDBC hibernate 和 ibatis 的區別

jdbc:手動
手動寫sql
delete、insert、update要將對象的值一個一個取出傳到sql中,不能直接傳入一個對象。
select:返回的是一個resultset,要從ResultSet中一行一行、一個字段一個字段的取出,然后封裝到一個對象中,不直接返回一個對象。
ibatis的特點:半自動化
sql要手動寫
delete、insert、update:直接傳入一個對象
select:直接返回一個對象
hibernate:全自動
不寫sql,自動封裝
delete、insert、update:直接傳入一個對象
select:直接返回一個對象

19、在數據庫中條件查詢速度很慢的時候,如何優化?

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

20、什么是SessionFactory,她是線程安全么?

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

21、Hibernate的五個核心接口

Configuration 接口:配置Hibernate,根據其啟動hibernate,創建
SessionFactory 對象;
SessionFactory 接口:初始化Hibernate,充當數據存儲源的代理,創建
session 對象,sessionFactory 是線程安全的,意味着它的同一個實例可以被應
用的多個線程共享,是重量級、二級緩存;
Session 接口:負責保存、更新、刪除、加載和查詢對象,是線程不安全的,
避免多個線程共享同一個session,是輕量級、一級緩存;
Transaction 接口:管理事務;
Query 和Criteria 接口:執行數據庫的查詢。
22.hibernate中sorted collection和ordered collection有什么不同? 

T這個是你會碰到的所有Hibernate面試問題中比較容易的問題。

sorted collection是通過使用 Java的Comparator在內存中進行排序的,

ordered collection中的排序用的是數據庫的order by子句。

對於比較大的數據集,為了避免在內存中對它們進行排序而出現 Java中的OutOfMemoryError,最好使用ordered collection。

23、什么是ORM? 

答:對象關系映射(Object-Relational Mapping,簡稱ORM)是一種為了解決程序的面向對象模型與數據庫的關系模型互不匹配問題的技術;簡單的說,ORM是通過使用描述對象和數據庫之間映射的元數據(在Java中可以用XML或者是注解),將程序中的對象自動持久化到關系數據庫中或者將關系數據庫表中的行轉換成Java對象,其本質上就是將數據從一種形式轉換到另外一種形式。
24.、Hibernate中SessionFactory是線程安全的嗎?Session是線程安全的嗎(兩個線程能夠共享同一個Session嗎)? 

答:SessionFactory對應Hibernate的一個數據存儲的概念,它是線程安全的,可以被多個線程並發訪問。SessionFactory一般只會在啟動的時候構建。對於應用程序,最好將SessionFactory通過單例模式進行封裝以便於訪問。Session是一個輕量級非線程安全的對象(線程間不能共享session),它表示與數據庫進行交互的一個工作單元。Session是由SessionFactory創建的,在任務完成之后它會被關閉。Session是持久層服務對外提供的主要接口。Session會延遲獲取數據庫連接(也就是在需要的時候才會獲取)。為了避免創建太多的session,可以使用ThreadLocal將session和當前線程綁定在一起,這樣可以讓同一個線程獲得的總是同一個session。Hibernate 3中SessionFactory的getCurrentSession()方法就可以做到。

25、闡述Session加載實體對象的過程。
答:Session加載實體對象的步驟是:
① Session在調用數據庫查詢功能之前,首先會在一級緩存中通過實體類型和主鍵進行查找,如果一級緩存查找命中且數據狀態合法,則直接返回;
② 如果一級緩存沒有命中,接下來Session會在當前NonExists記錄(相當於一個查詢黑名單,如果出現重復的無效查詢可以迅速做出判斷,從而提升性能)中進行查找,如果NonExists中存在同樣的查詢條件,則返回null;
③ 如果一級緩存查詢失敗則查詢二級緩存,如果二級緩存命中則直接返回;
④ 如果之前的查詢都未命中,則發出SQL語句,如果查詢未發現對應記錄則將此次查詢添加到Session的NonExists中加以記錄,並返回null;
⑤ 根據映射配置和SQL語句得到ResultSet,並創建對應的實體對象;
⑥ 將對象納入Session(一級緩存)的管理;
⑦ 如果有對應的攔截器,則執行攔截器的onLoad方法;
⑧ 如果開啟並設置了要使用二級緩存,則將數據對象納入二級緩存;
⑨ 返回數據對象。

26、Query接口的list方法和iterate方法有什么區別?
答:
① list()方法無法利用一級緩存和二級緩存(對緩存只寫不讀),它只能在開啟查詢緩存的前提下使用查詢緩存;iterate()方法可以充分利用緩存,如果目標數據只讀或者讀取頻繁,使用iterate()方法可以減少性能開銷。
② list()方法不會引起N+1查詢問題,而iterate()方法可能引起N+1查詢問題

 27、鎖機制有什么用?簡述Hibernate的悲觀鎖和樂觀鎖機制。 

答:有些業務邏輯在執行過程中要求對數據進行排他性的訪問,於是需要通過一些機制保證在此過程中數據被鎖住不會被外界修改,這就是所謂的鎖機制。
Hibernate支持悲觀鎖和樂觀鎖兩種鎖機制。悲觀鎖,顧名思義悲觀的認為在數據處理過程中極有可能存在修改數據的並發事務(包括本系統的其他事務或來自外部系統的事務),於是將處理的數據設置為鎖定狀態。悲觀鎖必須依賴數據庫本身的鎖機制才能真正保證數據訪問的排他性,關於數據庫的鎖機制和事務隔離級別在《Java面試題大全(上)》中已經討論過了。樂觀鎖,顧名思義,對並發事務持樂觀態度(認為對數據的並發操作不會經常性的發生),通過更加寬松的鎖機制來解決由於悲觀鎖排他性的數據訪問對系統性能造成的嚴重影響。最常見的樂觀鎖是通過數據版本標識來實現的,讀取數據時獲得數據的版本號,更新數據時將此版本號加1,然后和數據庫表對應記錄的當前版本號進行比較,如果提交的數據版本號大於數據庫中此記錄的當前版本號則更新數據,否則認為是過期數據無法更新。Hibernate中通過Session的get()和load()方法從數據庫中加載對象時可以通過參數指定使用悲觀鎖;而樂觀鎖可以通過給實體類加整型的版本字段再通過XML或@Version注解進行配置。

提示:使用樂觀鎖會增加了一個版本字段,很明顯這需要額外的空間來存儲這個版本字段,浪費了空間,但是樂觀鎖會讓系統具有更好的並發性,這是對時間的節省。
因此樂觀鎖也是典型的空間換時間的策略。

28、如何理解Hibernate的延遲加載機制?在實際應用中,延遲加載與Session關閉的矛盾是如何處理的?
答:延遲加載就是並不是在讀取的時候就把數據加載進來,而是等到使用時再加載。Hibernate使用了虛擬代理機制實現延遲加載,我們使用Session的load()方法加載數據或者一對多關聯映射在使用延遲加載的情況下從一的一方加載多的一方,得到的都是虛擬代理,簡單的說返回給用戶的並不是實體本身,而是實體對象的代理。代理對象在用戶調用getter方法時才會去數據庫加載數據。但加載數據就需要數據庫連接。而當我們把會話關閉時,數據庫連接就同時關閉了。

延遲加載與session關閉的矛盾一般可以這樣處理:
① 關閉延遲加載特性。這種方式操作起來比較簡單,因為Hibernate的延遲加載特性是可以通過映射文件或者注解進行配置的,但這種解決方案存在明顯的缺陷。首先,出現"no session or session was closed"通常說明系統中已經存在主外鍵關聯,如果去掉延遲加載的話,每次查詢的開銷都會變得很大。
② 在session關閉之前先獲取需要查詢的數據,可以使用工具方法Hibernate.isInitialized()判斷對象是否被加載,如果沒有被加載則可以使用Hibernate.initialize()方法加載對象。
③ 使用攔截器或過濾器延長Session的生命周期直到視圖獲得數據。Spring整合Hibernate提供的OpenSessionInViewFilter和OpenSessionInViewInterceptor就是這種做法。

 29.談一談Hibernate的一級緩存、二級緩存和查詢緩存。 

答:Hibernate的Session提供了一級緩存的功能,默認總是有效的,當應用程序保存持久化實體、修改持久化實體時,Session並不會立即把這種改變提交到數據庫,而是緩存在當前的Session中,除非顯示調用了Session的flush()方法或通過close()方法關閉Session。通過一級緩存,可以減少程序與數據庫的交互,從而提高數據庫訪問性能。
SessionFactory級別的二級緩存是全局性的,所有的Session可以共享這個二級緩存。不過二級緩存默認是關閉的,需要顯示開啟並指定需要使用哪種二級緩存實現類(可以使用第三方提供的實現)。一旦開啟了二級緩存並設置了需要使用二級緩存的實體類,SessionFactory就會緩存訪問過的該實體類的每個對象,除非緩存的數據超出了指定的緩存空間。
一級緩存和二級緩存都是對整個實體進行緩存,不會緩存普通屬性,如果希望對普通屬性進行緩存,可以使用查詢緩存。查詢緩存是將HQL或SQL語句以及它們的查詢結果作為鍵值對進行緩存,對於同樣的查詢可以直接從緩存中獲取數據。查詢緩存默認也是關閉的,需要顯示開啟。

30.Hibernate中DetachedCriteria類是做什么的?
答:DetachedCriteria和Criteria的用法基本上是一致的,但Criteria是由Session的createCriteria()方法創建的,也就意味着離開創建它的Session,Criteria就無法使用了。DetachedCriteria不需要Session就可以創建(使用DetachedCriteria.forClass()方法創建),所以通常也稱其為離線的Criteria,在需要進行查詢操作的時候再和Session綁定(調用其getExecutableCriteria(Session)方法),這也就意味着一個DetachedCriteria可以在需要的時候和不同的Session進行綁定。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM