首頁 後端開發 C#.Net教程 關於hibernate快取的問題:

關於hibernate快取的問題:

Dec 20, 2016 pm 02:19 PM
hibernate

1.     關於hibernate快取的問題:
1.1.1.        基本的快取原理
Hibernate快取分為二級,而第一級存放於session中稱為一級快取,預設有且無法卸載。
 
第二級是由sessionFactory控制的進程級快取。是全域共享的緩存,凡是會呼叫二級快取的查詢方法 都會從中受益。只有經過正確的配置後二級快取才會發揮作用。同時在進行條件查詢時必須使用對應的方法才能從快取中取得資料。例如Query.iterate()方法、load、get方法等。必須注意的是session.find方法永遠是從資料庫中獲取數據,不會從二級快取中獲取數據,即便其中有其所需的數據也是如此。
 
查詢時使用快取的實現過程為:首先查詢一級快取中是否具有需要的數據,如果沒有,查詢二級緩存,如果二級快取中也沒有,此時再執行查詢資料庫的工作。要注意的是:此3種方式的查詢速度是依序降低的。
1.2.   存在的問題
1.2.1.      一級快取的問題以及使用二級快取的原因
     因為Session的生命期往往很短,而存在於Session內部的第一級最快快取的生命期當然也很短,存在於Session內部的第一級最快的生命期當然也短,所以第一級快取的命中率是很低的。其對系統性能的改善也是很有限的。當然,這個Session內部快取的主要功能是保持Session內部資料狀態同步。並非是hibernate為了大幅提高系統效能所提供的。
為了提高使用hibernate的效能,除了常規的一些需要注意的方法例如:
使用延遲載入、迫切外連接、查詢過濾等以外,還需要配置hibernate的二級快取。其對系統整體性能的改善往往具有立竿見影的效果!
(經過自己先前作專案的經驗,一般會有3~4倍的效能提升)
 
1.2.2.      N+1次查詢的問題
執行條件查詢時,iterate()方法具有著名的「n+ 1」次查詢的問題,也就是說在第一次查詢時iterate方法會執行滿足條件的查詢結果數再加一次(n+1)的查詢。但是此問題只存在於第一次查詢時,在後面執行相同查詢時效能會得到極大的改善。此方法適合查詢資料量較大的業務資料。
但是注意:當資料量特別大時(例如管線資料等)需要針對此持久化物件配置其特定的快取策略,例如設定其存在於快取中的最大記錄數、快取存在的時間等參數,以避免系統將大量的資料同時裝載入記憶體中引起記憶體資源的快速耗盡,反而降低系統的效能! ! !
 
1.3.   使用hibernate二級快取的其他注意事項:
1.3.1.      關於資料的有效性
另外,hibernate會自行維護以確保快取中的資料和資料庫中的真實資料的一致性!無論何時,當你呼叫save()、update()或saveOrUpdate()方法傳遞一個物件時,或使用load()、 get()、list()、iterate() 或scroll()方法取得一個物件時, 該物件都將被加入到Session的內部快取中。 當隨後flush()方法被呼叫時,物件的狀態會和資料庫取得同步。
 
也就是說刪除、更新、增加資料的時候,同時更新快取。當然這也包括二級緩存!
 
只要是呼叫hibernate API執行資料庫相關的工作。 hibernate都會為你自動保證 快取資料的有效性! !
 
但是,如果你使用了JDBC繞過hibernate直接執行對資料庫的操作。此時,Hibernate不會/也不可能自行感知到資料庫被進行的變化改動,也就不能再保證快取中資料的有效性! !
 
這也是所有的ORM產品共同具有的問題。幸運的是,Hibernate為我們揭露了Cache的清除方法,這給了我們一個手動保證資料有效性的機會! !
一級緩存,二級緩存都有相應的清除方法。
 
其中二級快取提供的清除方法為:
按物件class清空快取
               
   

1.3.2.      適合使用的情況
並非所有的情況都適合於使用二級緩存,需要根據具體情況來決定。同時可以針對某一個持久化物件配置其具體的快取策略。
 
適合使用二級快取的情況:
1、資料不會被第三方修改;
 
一般情況下,會被hibernate以外修改的資料最好不要配置二級緩存,以免造成不一致的資料。但如果此資料因為效能的原因需要被緩存,同時又有可能被第3方例如SQL修改,也可以為其配置二級快取。只是此時需要在sql執行修改後手動呼叫cache的清除方法。以確保資料的一致性
 
  2、資料大小在可接收範圍之內;
 
     如果資料表資料量特別龐大,此時不適合於二級快取。原因是快取的資料量過大可能會造成記憶體資源緊張,反而降低效能。
 
如果資料表資料量特別龐大,但是經常使用的往往只是較新的那部分資料。此時,也可為其配置二級快取。但必須單獨配置其持久化類別的快取策略,例如最大快取數、快取過期時間等,將這些參數降低至合理的範圍(太高會造成記憶體資源緊張,太低了快取的意義不大)。
 
  3、數據更新頻率低;
 
     對於數據更新頻率過高的數據,頻繁同步緩存中數據的代價可能和 查詢緩存中的數據從中獲得的好處相當,壞處益處相抵消。此時快取的意義也不大。
 
 
  4、非關鍵數據(不是財務數據等)
 
  財務數據等是非常重要的數據,絕對不允許出現或使用無效的數據,所以此時為了安全起見最好不要使用二級緩存。
  因為此時 「正確性」的重要性遠大於 「高績效」的重要性。
 
2.     在系統中使用hibernate快取的建議
1.4.   目前狀況
 一般系統中有三種情況會繞過hibernate執行資料庫操作:

1、多個應用系統同時存取一個資料庫使用資料來源二級快取會不可避免的造成資料不一致的問題,
   此時要進行詳細的設計。例如在設計上避免對相同資料表的同時的寫入操作,
   使用資料庫各種層級的鎖定機制等。
 
2、動態表相關

   所謂「動態表」是指在系統運作時會根據使用者的作業系統自動建立的資料表。

   例如「自訂表單」等屬於使用者自訂擴充功能開發性質的功能模組,因為此時資料表是執行時間建立的,所以不能進行hibernate的對應。因此對它的操作只能是繞過hibernate的直接資料庫JDBC操作。

      如果此時動態表中的資料沒有設計緩存,就沒有資料不一致的問題。

   如果此時自行設計了快​​取機制,則呼叫自己的快取同步方法即可。

3、使用sql對hibernate持久化物件表進行批次刪除時

     此時執行批次刪除後,快取中會存在已刪除的資料。

分析: 
   當執行了第3條(sql批次刪除)後,後續的查詢只可能是以下三種方式:
a. session.find()方法:
根據前面的總結,find方法不會查詢二級快取的數據,而是直接查詢資料庫。
所以不存在數據有效性的問題。
b. 呼叫iterate方法執行條件查詢時:
根據iterate查詢方法的執行方式,其每次都會到數據庫中查詢滿足條件的id值,然後再根據此id 到緩存中獲取數據,當緩存中沒有此id的資料才會執行資料庫查詢;
如果此記錄已被sql直接刪除,則iterate在執行id查詢時不會將此id查詢出來。所以,即便快取中有此筆記錄也不會被客戶取得,也就不存在不一致的情況。 (此情況經過測試驗證)
 
c. 用get或load方法按id執行查詢:
 
客觀上此時會查詢得到已過期的資料。但又因為系統中執行sql批量刪除一般是

針對中間關聯資料表,對於

中間關聯表的查詢通常都是採用條件查詢,按id來查詢某一條關聯關係的幾率很低,所以此問題也不存在!
 
   如果某個值對象確實需要按id查詢一條關聯關係,同時又因為資料量大使用了sql執行批次刪除。當滿足此兩個條件時,為了保證按id 的查詢得到正確的結果,可以使用手動清楚二級緩存中此對象的數據的方法!!
(此種情況出現的可能性較小)
 
1.5 .   建議
1、建議不要使用sql直接執行資料持久化物件的資料的更新,但是可以執行批次刪除。 (系統中需要批次更新的地方也較少)
 
2、如果必須使用sql執行資料的更新,必須清空此物件的快取資料。呼叫
SessionFactory.evict(class) 
SessionFactory.evict(class,id)
等方法。
 
3、在批次刪除資料量不大的時候可以直接採用hibernate的批次刪除,這樣就不存在繞開hibernate執行sql產生的快取資料一致性的問題。
 
4、不建議採用hibernate的批次刪除方法來刪除大量的記錄資料。
原因是hibernate的批次刪除會執行1個查詢語句外加 滿足條件的n條刪除語句。而不是一次執行一條條件刪除語句! ! 
當待刪除的資料很多時會有很大的效能瓶頸! ! !如果大量刪除資料量較大,例如超過50條,可以採用JDBC直接刪除。這樣作的好處是只執行一條sql刪除語句,效能會有很大的改善。同時,快取資料同步的問題,可以採用 hibernate清除二級快取中的相關資料的方法。
呼叫 SessionFactory.evict(class) ;SessionFactory.evict(class,id)等方法。
 
所以說,對於一般的應用系統開發而言(不涉及到集群,分佈式資料同步問題等),因為只在中間關聯表執行批量刪除時調用了sql執行,同時中間關聯表一般是執行條件查詢不太可能執行按id查詢。所以,此時可以直接執行sql刪除,甚至不需要呼叫快取的清除方法。這樣做不會導致日後配置了二級快取造成資料有效性的問題。
 
退一步說,即使以後真的呼叫了按id查詢中間表物件的方法,也可以透過呼叫清除快取的方法來解決。

 

4、具體的配置方法 
根據我了解的很多hibernate的用戶在調用其相應方法時都迷信的相信“hibernate會自行為我們處理性能的問題”,或者“hibernate會自動為我們的所有操作調用緩存”,實際的情況是hibernate雖然為我們提供了很好的緩存機制和擴展緩存框架的支持,但是必須經過正確的調用其才有可能發揮作用! !所以造成很多使用hibernate的系統的效能問題,其實並不是hibernate不行或不好,而是因為使用者沒有正確的了解其使用方法造成的。相反,如果配置得當hibernate的性能表現會讓你有相當“驚喜的”發現。下面我說明特定的設定方法.

 ibernate提供了二級快取的介面: 
net.sf.hibernate.cache.Provider, 
同時提供了一個預設的實作net.sf.hibernate.cache.HashtableCacheProvider, 可以配置其他的實作例如ehcache,jbosscache等。

具體的設定位置位於hibernate.cfg.xml檔案中 

true 
natesf. .cache.HashtableCacheProvider

很多的hibernate使用者在設定到這一步驟就以為完事了, 

注意:其實光這樣配,根本就沒有使用hibernate的二級快取。同時因為他們在使用hibernate時大多時候是馬上關閉session,所以,一級快取也沒有起到任何作用。結果就是沒有使用任何緩存,所有的hibernate操作都是直接操作的資料庫! !性能可以想見。

正確的方法是除了以上的配置外還應該配置每個vo物件的特定快取策略,在影射檔案中配置。例如:

 

 
 
 name="id" column="TYPEID" type="java.lang.Long"> 
 

 
 
 


關鍵就是這個,其有幾個選擇 
read-only,read-write,transactional,等 
然後在執行查詢時注意了,如果是條件查詢,或傳回所有結果的查詢,此時session.find()方法不會取得快取中的資料。只有在呼叫query.iterate()方法時才會調快取的資料。

同時get 和load方法是都會查詢快取中的資料.

對於不同的快取框架具體的配置方法會有不同,但是大體是以上的配置

(另外,對於支援事務型,以及支援叢集的環境的配置我會爭取在後續的文章中發表出來)

 

3.     總結
總之是根據不同的業務狀況和專案狀況對hibernate進行有效的配置和正確的使用,揚長避短。不存在適合於任何情況的一個「萬能」的方案。


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1321
25
PHP教程
1269
29
C# 教程
1249
24
SpringBoot專案裡怎麼整合Hibernate SpringBoot專案裡怎麼整合Hibernate May 18, 2023 am 09:49 AM

在SpringBoot專案中整合Hibernate前言Hibernate是一個流行的ORM(物件關係映射)框架,它可以將Java物件映射到資料庫表,從而方便地進行持久化操作。在SpringBoot專案中,整合Hibernate可以幫助我們更輕鬆地進行資料庫操作,本文將介紹如何在SpringBoot專案中整合Hibernate,並提供相應的範例。 1.引入依賴在pom.xml檔案中引入以下依賴:org.springframework.bootspring-boot-starter-data-jpam

Java錯誤:Hibernate錯誤,如何處理與避免 Java錯誤:Hibernate錯誤,如何處理與避免 Jun 25, 2023 am 09:09 AM

Java是一種物件導向程式語言,它被廣泛地應用於軟體開發領域。 Hibernate是一種流行的Java持久化框架,它提供了一種簡單且高效的方式來管理Java物件的持久化。然而,開發過程中經常會遇到Hibernate錯誤,這些錯誤可能會導致程式的異常終止或不穩定。如何處理和避免Hibernate錯誤成為了Java開發者必須掌握的能力。本文將介紹一些常見的Hib

hibernate和mybatis有哪些差別 hibernate和mybatis有哪些差別 Jan 03, 2024 pm 03:35 PM

hibernate和mybatis的差別:1、實作方式;2、效能;3、物件管理的比較;4、快取機制。詳細介紹:1、實作方式,Hibernate是一個完整的物件/關係映射解決方案,將物件與資料庫表進行映射,MyBatis則需要開發者手動編寫SQL語句以及ResultMap;2、效能,Hibernate在開發速度上可能比MyBatis快,因為Hibernate簡化了DAO層等等。

Java Hibernate中一對多與多對多關係的對應方式是什麼 Java Hibernate中一對多與多對多關係的對應方式是什麼 May 27, 2023 pm 05:06 PM

Hibernate的一對多和多對多Hibernate是一個優秀的ORM框架,它簡化了Java應用程式與關係型資料庫之間的資料存取。在Hibernate中,我們可以使用一對多和多對多的關係來處理複雜的資料模型。 Hibernate的一對多在Hibernate中,一對多關係是指一個實體類別對應多個另一個實體類別。例如,一個訂單(Order)可以對應多個訂單項目(OrderItem),一個使用者(User)可以對應多個訂單(Order)。要在Hibernate中實作一對多關係,需要在實體類別中定義一個集合屬性來存

Java語言中的Hibernate框架介紹 Java語言中的Hibernate框架介紹 Jun 10, 2023 am 11:35 AM

Hibernate是一個開放原始碼的ORM框架,它將關係型資料庫和Java程式之間的資料映射相互綁定,這樣可以讓開發人員更方便地存取資料庫中的資料。使用Hibernate框架可以大幅減少編寫SQL語句的工作,並提高應用程式的開發效率和可重複使用性。以下從以下幾個方面來介紹Hibernate框架。一、Hibernate框架的優點物件關係映射,隱藏資料庫存取細節,使開發

Java中如何設定Hibernate環境 Java中如何設定Hibernate環境 Apr 26, 2023 am 11:55 AM

1.hibernate映射配置class標籤,用來建立類別與表之間的關係name:類別名,table:表名id標籤,建立中的屬性與表中的主鍵的對應關係property,建立類別中的普通屬性與表格的欄位的對應關係(1)首先我們要學會如何編寫映射配置文件,大家要知道編寫完的映射配置文件應與實體類在同一個包下,並且名稱應是類名.hbm.xml,所以我們要在com.meimeixia.hibernate.demo01套件下建立一個Customer.hbm.xml文件,但是它的限制該怎麼寫呢?可以在Hiberna

Hibernate二級快取是如何運作的? Hibernate二級快取是如何運作的? Sep 14, 2023 pm 07:45 PM

快取有助於減少執行查詢時的資料庫網路呼叫。一級緩存與會話連結。它是隱式實現的。一級緩存存在直到會話物件存在為止。一旦會話物件終止/關閉,將會有沒有快取物件。二級緩存適用於多個會話物件。它是連結的與會話工廠。二級緩存物件可供所有會話使用單一會話工廠。當特定會話發生時,這些快取物件將被終止工廠已關閉。實作二級快取我們需要新增以下相依性才能使用二級快取。 <!--https://mvnrepository.com/artifact/net.sf.ehcache/ehcache--><de

如何在Hibernate中執行批次插入更新操作? 如何在Hibernate中執行批次插入更新操作? Aug 27, 2023 pm 11:17 PM

在本文中,我們將看到如何在Hibernate中執行批次插入/更新。每當我們執行一條sql語句時,我們都是透過對資料庫進行網路呼叫來完成的。現在,如果我們必須在資料庫表中插入10個條目,那麼我們必須進行10次網路呼叫。相反,我們可以透過使用批次來優化網路呼叫。批次允許我們在單一網路呼叫中執行一組SQL語句。為了理解和實作這一點,讓我們定義我們的實體−@EntitypublicclassParent{@Id@GeneratedValue(strategy=GenerationType.AUTO)

See all articles