當前位置:首頁 » 文件管理 » hibernate一級緩存關閉

hibernate一級緩存關閉

發布時間: 2023-01-25 09:54:24

❶ hibernate一級緩存和二級緩存的區別

一級緩存為 session緩存,二級緩存是sessionfactory緩存。

❷ 怎樣解決hibernate中一級緩存導致數據不能刷新

Hibernate的一級緩存是由Session提供的,因此它只存在於Session的生命周期中,也就是當Session關閉的時候該Session所管理的一級緩存也會立即被清除。

Hibernate的一級緩存是Session所內置的,不能被卸載,也不能進行任何配置。

一級緩存採用的是key-value的Map方式來實現的,在緩存實體對象時,對象的主關鍵字ID是Map的key,實體對象就是對應的值。所以說,一級緩存是以實體對象為單位進行存儲的,在訪問的時候使用的是主關鍵字ID。

雖然,Hibernate對一級緩存使用的是自動維護的功能,沒有提供任何配置功能,但是可以通過Session中所提供的方法來對一級緩存的管理進行手工干預。Session中所提供的干預方法包括以下兩種。

evict() :用於將某個對象從Session的一級緩存中清除。

clear() :用於將一級緩存中的對象全部清除。

在進行大批量數據一次性更新的時候,會佔用非常多的內存來緩存被更新的對象。這時就應該階段性地調用clear()方法來清空一級緩存中的對象,控制一級緩存的大小,以避免產生內存溢出的情況。

❸ hibernate 二級緩存和查詢緩存有什麼區別

一級緩存為session級別的緩存,為hibernate內置緩存,你從資料庫load或get數據的時候會先去一級緩存上找。如果找到,則不會從資料庫中存,否則從資料庫中取。一級緩存會在session關閉時自動清除。
二級緩存為SessionFactory級別的緩存,要使用第三方二級緩存組件,不同session可以共享二級緩存中的數據!
查詢緩存就是hql或sql語句要相同,否則無法命中數據

❹ hibernate緩存的詳細配置

很多人對二級緩存都不太了解,或者是有錯誤的認識,我一直想寫一篇文章介紹一下hibernate的二級緩存的,今天終於忍不住了。
我的經驗主要來自hibernate2.1版本,基本原理和3.0、3.1是一樣的,請原諒我的頑固不化。

hibernate的session提供了一級緩存,每個session,對同一個id進行兩次load,不會發送兩條sql給資料庫,但是session關閉的時候,一級緩存就失效了。

二級緩存是SessionFactory級別的全局緩存,它底下可以使用不同的緩存類庫,比如ehcache、oscache等,需要設置hibernate.cache.provider_class,我們這里用ehcache,在2.1中就是
hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider
如果使用查詢緩存,加上
hibernate.cache.use_query_cache=true

緩存可以簡單的看成一個Map,通過key在緩存裡面找value。

Class的緩存
對於一條記錄,也就是一個PO來說,是根據ID來找的,緩存的key就是ID,value是POJO。無論list,load還是iterate,只要讀出一個對象,都會填充緩存。但是list不會使用緩存,而iterate會先取資料庫select id出來,然後一個id一個id的load,如果在緩存裡面有,就從緩存取,沒有的話就去資料庫load。假設是讀寫緩存,需要設置:
<cache usage="read-write"/>
如果你使用的二級緩存實現是ehcache的話,需要配置ehcache.xml
<cache name="com.xxx.pojo.Foo" maxElementsInMemory="500" eternal="false" timeToLiveSeconds="7200" timeToIdleSeconds="3600" overflowToDisk="true" />
其中eternal表示緩存是不是永遠不超時,timeToLiveSeconds是緩存中每個元素(這里也就是一個POJO)的超時時間,如果eternal="false",超過指定的時間,這個元素就被移走了。timeToIdleSeconds是發呆時間,是可選的。當往緩存裡面put的元素超過500個時,如果overflowToDisk="true",就會把緩存中的部分數據保存在硬碟上的臨時文件裡面。
每個需要緩存的class都要這樣配置。如果你沒有配置,hibernate會在啟動的時候警告你,然後使用defaultCache的配置,這樣多個class會共享一個配置。
當某個ID通過hibernate修改時,hibernate會知道,於是移除緩存。
這樣大家可能會想,同樣的查詢條件,第一次先list,第二次再iterate,就可以使用到緩存了。實際上這是很難的,因為你無法判斷什麼時候是第一次,而且每次查詢的條件通常是不一樣的,假如資料庫裡面有100條記錄,id從1到100,第一次list的時候出了前50個id,第二次iterate的時候卻查詢到30至70號id,那麼30-50是從緩存裡面取的,51到70是從資料庫取的,共發送1+20條sql。所以我一直認為iterate沒有什麼用,總是會有1+N的問題。
(題外話:有說法說大型查詢用list會把整個結果集裝入內存,很慢,而iterate只select id比較好,但是大型查詢總是要分頁查的,誰也不會真的把整個結果集裝進來,假如一頁20條的話,iterate共需要執行21條語句,list雖然選擇若干欄位,比iterate第一條select id語句慢一些,但只有一條語句,不裝入整個結果集hibernate還會根據資料庫方言做優化,比如使用mysql的limit,整體看來應該還是list快。)
如果想要對list或者iterate查詢的結果緩存,就要用到查詢緩存了

查詢緩存
首先需要配置hibernate.cache.use_query_cache=true
如果用ehcache,配置ehcache.xml,注意hibernate3.0以後不是net.sf的包名了
<cache name="net.sf.hibernate.cache.StandardQueryCache"
maxElementsInMemory="50" eternal="false" timeToIdleSeconds="3600"
timeToLiveSeconds="7200" overflowToDisk="true"/>
<cache name="net.sf.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="5000" eternal="true" overflowToDisk="true"/>
然後
query.setCacheable(true);//激活查詢緩存
query.setCacheRegion("myCacheRegion");//指定要使用的cacheRegion,可選
第二行指定要使用的cacheRegion是myCacheRegion,即你可以給每個查詢緩存做一個單獨的配置,使用setCacheRegion來做這個指定,需要在ehcache.xml裡面配置它:
<cache name="myCacheRegion" maxElementsInMemory="10" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200" overflowToDisk="true" />
如果省略第二行,不設置cacheRegion的話,那麼會使用上面提到的標准查詢緩存的配置,也就是net.sf.hibernate.cache.StandardQueryCache

對於查詢緩存來說,緩存的key是根據hql生成的sql,再加上參數,分頁等信息(可以通過日誌輸出看到,不過它的輸出不是很可讀,最好改一下它的代碼)。
比如hql:
from Cat c where c.name like ?
生成大致如下的sql:
select * from cat c where c.name like ?
參數是"tiger%",那麼查詢緩存的key*大約*是這樣的字元串(我是憑記憶寫的,並不精確,不過看了也該明白了):
select * from cat c where c.name like ? , parameter:tiger%
這樣,保證了同樣的查詢、同樣的參數等條件下具有一樣的key。
現在說說緩存的value,如果是list方式的話,value在這里並不是整個結果集,而是查詢出來的這一串ID。也就是說,不管是list方法還是iterate方法,第一次查詢的時候,它們的查詢方式很它們平時的方式是一樣的,list執行一條sql,iterate執行1+N條,多出來的行為是它們填充了緩存。但是到同樣條件第二次查詢的時候,就都和iterate的行為一樣了,根據緩存的key去緩存裡面查到了value,value是一串id,然後在到class的緩存裡面去一個一個的load出來。這樣做是為了節約內存。
可以看出來,查詢緩存需要打開相關類的class緩存。list和iterate方法第一次執行的時候,都是既填充查詢緩存又填充class緩存的。
這里還有一個很容易被忽視的重要問題,即打開查詢緩存以後,即使是list方法也可能遇到1+N的問題!相同條件第一次list的時候,因為查詢緩存中找不到,不管class緩存是否存在數據,總是發送一條sql語句到資料庫獲取全部數據,然後填充查詢緩存和class緩存。但是第二次執行的時候,問題就來了,如果你的class緩存的超時時間比較短,現在class緩存都超時了,但是查詢緩存還在,那麼list方法在獲取id串以後,將會一個一個去資料庫load!因此,class緩存的超時時間一定不能短於查詢緩存設置的超時時間!如果還設置了發呆時間的話,保證class緩存的發呆時間也大於查詢的緩存的生存時間。這里還有其他情況,比如class緩存被程序強制evict了,這種情況就請自己注意了。

另外,如果hql查詢包含select字句,那麼查詢緩存裡面的value就是整個結果集了。

當hibernate更新資料庫的時候,它怎麼知道更新哪些查詢緩存呢?
hibernate在一個地方維護每個表的最後更新時間,其實也就是放在上面net.sf.hibernate.cache.UpdateTimestampsCache所指定的緩存配置裡面。
當通過hibernate更新的時候,hibernate會知道這次更新影響了哪些表。然後它更新這些表的最後更新時間。每個緩存都有一個生成時間和這個緩存所查詢的表,當hibernate查詢一個緩存是否存在的時候,如果緩存存在,它還要取出緩存的生成時間和這個緩存所查詢的表,然後去查找這些表的最後更新時間,如果有一個表在生成時間後更新過了,那麼這個緩存是無效的。
可以看出,只要更新過一個表,那麼凡是涉及到這個表的查詢緩存就失效了,因此查詢緩存的命中率可能會比較低。

Collection緩存
需要在hbm的collection裡面設置
<cache usage="read-write"/>
假如class是Cat,collection叫children,那麼ehcache裡面配置
<cache name="com.xxx.pojo.Cat.children"
maxElementsInMemory="20" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200"
overflowToDisk="true" />
Collection的緩存和前面查詢緩存的list一樣,也是只保持一串id,但它不會因為這個表更新過就失效,一個collection緩存僅在這個collection裡面的元素有增刪時才失效。
這樣有一個問題,如果你的collection是根據某個欄位排序的,當其中一個元素更新了該欄位時,導致順序改變時,collection緩存裡面的順序沒有做更新。

緩存策略
只讀緩存(read-only):沒有什麼好說的
讀/寫緩存(read-write):程序可能要的更新數據
不嚴格的讀/寫緩存(nonstrict-read-write):需要更新數據,但是兩個事務更新同一條記錄的可能性很小,性能比讀寫緩存好
事務緩存(transactional):緩存支持事務,發生異常的時候,緩存也能夠回滾,只支持jta環境,這個我沒有怎麼研究過

讀寫緩存和不嚴格讀寫緩存在實現上的區別在於,讀寫緩存更新緩存的時候會把緩存裡面的數據換成一個鎖,其他事務如果去取相應的緩存數據,發現被鎖住了,然後就直接取資料庫查詢。
在hibernate2.1的ehcache實現中,如果鎖住部分緩存的事務發生了異常,那麼緩存會一直被鎖住,直到60秒後超時。
不嚴格讀寫緩存不鎖定緩存中的數據。

使用二級緩存的前置條件
你的hibernate程序對資料庫有獨占的寫訪問權,其他的進程更新了資料庫,hibernate是不可能知道的。你操作資料庫必需直接通過hibernate,如果你調用存儲過程,或者自己使用jdbc更新資料庫,hibernate也是不知道的。hibernate3.0的大批量更新和刪除是不更新二級緩存的,但是據說3.1已經解決了這個問題。
這個限制相當的棘手,有時候hibernate做批量更新、刪除很慢,但是你卻不能自己寫jdbc來優化,很郁悶吧。
SessionFactory也提供了移除緩存的方法,你一定要自己寫一些JDBC的話,可以調用這些方法移除緩存,這些方法是:
void evict(Class persistentClass)
Evict all entries from the second-level cache.
void evict(Class persistentClass, Serializable id)
Evict an entry from the second-level cache.
void evictCollection(String roleName)
Evict all entries from the second-level cache.
void evictCollection(String roleName, Serializable id)
Evict an entry from the second-level cache.
void evictQueries()
Evict any query result sets cached in the default query cache region.
void evictQueries(String cacheRegion)
Evict any query result sets cached in the named query cache region.
不過我不建議這樣做,因為這樣很難維護。比如你現在用JDBC批量更新了某個表,有3個查詢緩存會用到這個表,用evictQueries(String cacheRegion)移除了3個查詢緩存,然後用evict(Class persistentClass)移除了class緩存,看上去好像完整了。不過哪天你添加了一個相關查詢緩存,可能會忘記更新這里的移除代碼。如果你的jdbc代碼到處都是,在你添加一個查詢緩存的時候,還知道其他什麼地方也要做相應的改動嗎?

----------------------------------------------------

總結:
不要想當然的以為緩存一定能提高性能,僅僅在你能夠駕馭它並且條件合適的情況下才是這樣的。hibernate的二級緩存限制還是比較多的,不方便用jdbc可能會大大的降低更新性能。在不了解原理的情況下亂用,可能會有1+N的問題。不當的使用還可能導致讀出臟數據。
如果受不了hibernate的諸多限制,那麼還是自己在應用程序的層面上做緩存吧。
在越高的層面上做緩存,效果就會越好。就好像盡管磁碟有緩存,資料庫還是要實現自己的緩存,盡管資料庫有緩存,咱們的應用程序還是要做緩存。因為底層的緩存它並不知道高層要用這些數據干什麼,只能做的比較通用,而高層可以有針對性的實現緩存,所以在更高的級別上做緩存,效果也要好些吧。

❺ Hibernate的緩存技術有哪些

緩存是資料庫數據在內存中的臨時容器,它包含了庫表數據在內存中的臨時拷貝,位於資料庫與應用程序之間,其作用是為了降低應用程序對物理數據源訪問的頻次,從而提高應用的運行性能。

Hibernate的緩存機制

1.1持久化層的緩存的范圍

持久層設計中,往往需要考慮幾個不同層次中的數據緩存策略。這些層次的劃分標准針對不同情況有所差異,一般而言,ORM的數據緩存應包含如下幾個層次:

事務級緩存(Transaction Layer Cache)

緩存只能被當前事務訪問。緩存的生命周期依賴於事務的生命周期,當事務結束時,緩存也就結束生命周期。在此范圍下,緩存的介質是內存。事務可以是資料庫事務或者應用事務,每個事務都有獨自的緩存,緩存內的數據通常採用相互關聯的對象形式。

應用級/進程級緩存(Application/Process Layer Cache)

緩存被進程內的所有事務共享。這些事務有可能是並發訪問緩存,因此必須對緩存採取必要的事務隔離機制。緩存的生命周期依賴於進程的生命周期,進程結束時,緩存也就結束了生命周期。進程范圍的緩存可能會存放大量的數據,所以存放的介質可以是內存或硬碟。緩存內的數據既可以是相互關聯的對象形式也可以是對象的鬆散數據形式。對象的鬆散數據形式有點類似於對象的序列化數據,但是對象分解為鬆散的演算法比對象序列化的演算法要求更快。

集群級緩存(Cluster Layer Cache)

在集群環境中,緩存被一個機器或者多個機器的進程共享。緩存中的數據被復制到集群環境中的每個進程節點,進程間通過遠程通信來保證緩存中的數據的一致性,緩存中的數據通常採用對象的鬆散數據形式。對大多數應用來說,應該慎重地考慮是否需要使用集群范圍的緩存,因為訪問的速度不一定會比直接訪問資料庫數據的速度快多少。

持久層提供以上多種層次的緩存。如果在事務級緩存中沒有查到相應的數據,還可以到進程級或集群級緩存內查詢,如果還是沒有查到,那麼只有到資料庫中查詢。事務級緩存是持久化層的第一級緩存,通常它是必需的;進程級或集群級緩存是持久化層的第二級緩存,通常是可選的。

1.2 hibernate緩存機制

Hibernate提供了兩種緩存,第一種是Session的緩存,又稱為一級緩存。由於Session對象的生命周期通常對應一個資料庫事務或者一個應用事務,因此它的緩存是事務范圍的緩存。第一級緩存是必需的,不允許而且事實上也無法卸除。在第一級緩存中,持久化類的每個實例都具有唯一的OID。

❻ hibernate工作原理及為什麼要用

hibernate 簡介:
hibernate是一個開源框架,它是對象關聯關系映射的框架,它對JDBC做了輕量級的封裝,而我們java程序員可以使用面向對象的思想來操縱資料庫。
hibernate核心介面
session:負責被持久化對象CRUD操作
sessionFactory:負責初始化hibernate,創建session對象
configuration:負責配置並啟動hibernate,創建SessionFactory
Transaction:負責事物相關的操作
Query和Criteria介面:負責執行各種資料庫查詢

hibernate工作原理:
1.通過Configuration config = new Configuration().configure();//讀取並解析hibernate.cfg.xml配置文件
2.由hibernate.cfg.xml中的<mapping resource="com/xx/User.hbm.xml"/>讀取並解析映射信息
3.通過SessionFactory sf = config.buildSessionFactory();//創建SessionFactory
4.Session session = sf.openSession();//打開Sesssion
5.Transaction tx = session.beginTransaction();//創建並啟動事務Transation
6.persistent operate操作數據,持久化操作
7.tx.commit();//提交事務
8.關閉Session
9.關閉SesstionFactory

為什麼要用hibernate:
1. 對JDBC訪問資料庫的代碼做了封裝,大大簡化了數據訪問層繁瑣的重復性代碼。
2. Hibernate是一個基於JDBC的主流持久化框架,是一個優秀的ORM實現。他很大程度的簡化DAO層的編碼工作
3. hibernate使用Java反射機制,而不是位元組碼增強程序來實現透明性。
4. hibernate的性能非常好,因為它是個輕量級框架。映射的靈活性很出色。它支持各種關系資料庫,從一對一到多對多的各種復雜關系。

Hibernate是如何延遲載入?get與load的區別
1. 對於Hibernate get方法,Hibernate會確認一下該id對應的數據是否存在,首先在session緩存中查找,然後在二級緩存中查找,還沒有就查詢資料庫,數據 庫中沒有就返回null。這個相對比較簡單,也沒有太大的爭議。主要要說明的一點就是在這個版本(bibernate3.2以上)中get方法也會查找二級緩存!
2. Hibernate load方法載入實體對象的時候,根據映射文件上類級別的lazy屬性的配置(默認為true),分情況討論:
(1)若為true,則首先在Session緩存中查找,看看該id對應的對象是否存在,不存在則使用延遲載入,返回實體的代理類對象(該代理類為實體類的子類,由CGLIB動態生成)。等到具體使用該對象(除獲取OID以外)的時候,再查詢二級緩存和資料庫,若仍沒發現符合條件的記錄,則會拋出一個ObjectNotFoundException。
(2)若為false,就跟Hibernateget方法查找順序一樣,只是最終若沒發現符合條件的記錄,則會拋出一個ObjectNotFoundException。
這里get和load有兩個重要區別:
如果未能發現符合條件的記錄,Hibernate get方法返回null,而load方法會拋出一個ObjectNotFoundException。
load方法可返回沒有載入實體數據的代 理類實例,而get方法永遠返回有實體數據的對象。
(對於load和get方法返回類型:好多書中都說:「get方法永遠只返回實體類」,實際上並不正 確,get方法如果在session緩存中找到了該id對應的對象,如果剛好該對象前面是被代理過的,如被load方法使用過,或者被其他關聯對象延遲加 載過,那麼返回的還是原先的代理對象,而不是實體類對象,如果該代理對象還沒有載入實體數據(就是id以外的其他屬性數據),那麼它會查詢二級緩存或者數 據庫來載入數據,但是返回的還是代理對象,只不過已經載入了實體數據。)
總之對於get和load的根本區別,一句話,hibernate對於 load方法認為該數據在資料庫中一定存在,可以放心的使用代理來延遲載入,如果在使用過程中發現了問題,只能拋異常;而對於get方 法,hibernate一定要獲取到真實的數據,否則返回null。

Hibernate中怎樣實現類之間的關系?(如:一對多、多對多的關系)
類與類之間的關系主要體現在表與表之間的關系進行操作,它們都市對對象進行操作,我們程序中把所有的表與類都映射在一起,它們通過配置文件中的many-to-one、one-to-many、many-to-many、

說下Hibernate的緩存機制:
Hibernate緩存的作用:
Hibernate是一個持久層框架,經常訪問物理資料庫,為了降低應用程序對物理數據源訪問的頻次,從而提高應用程序的運行性能。緩存內的數據是對物理數據源中的數據的復制,應用程序在運行時從緩存讀寫數據,在特定的時刻或事件會同步緩存和物理數據源的數據
Hibernate緩存分類:
Hibernate緩存包括兩大類:Hibernate一級緩存和Hibernate二級緩存
Hibernate一級緩存又稱為「Session的緩存」,它是內置的,意思就是說,只要你使用hibernate就必須使用session緩存。由於Session對象的生命周期通常對應一個資料庫事務或者一個應用事務,因此它的緩存是事務范圍的緩存。在第一級緩存中,持久化類的每個實例都具有唯一的OID。
Hibernate二級緩存又稱為「SessionFactory的緩存」,由於SessionFactory對象的生命周期和應用程序的整個過程對應,因此Hibernate二級緩存是進程范圍或者集群范圍的緩存,有可能出現並發問題,因此需要採用適當的並發訪問策略,該策略為被緩存的數據提供了事務隔離級別。第二級緩存是可選的,是一個可配置的插件,在默認情況下,SessionFactory不會啟用這個插件。

什麼樣的數據適合存放到第二級緩存中?
1 很少被修改的數據
2 不是很重要的數據,允許出現偶爾並發的數據
3 不會被並發訪問的數據
4 常量數據
不適合存放到第二級緩存的數據?
1經常被修改的數據
2 .絕對不允許出現並發訪問的數據,如財務數據,絕對不允許出現並發
3 與其他應用共享的數據。

Hibernate查找對象如何應用緩存?
當Hibernate根據ID訪問數據對象的時候,首先從Session一級緩存中查;查不到,如果配置了二級緩存,那麼從二級緩存中查;如果都查不到,再查詢資料庫,把結果按照ID放入到緩存
刪除、更新、增加數據的時候,同時更新緩存

Hibernate管理緩存實例
無論何時,我們在管理Hibernate緩存(Managing the caches)時,當你給save()、update()或saveOrUpdate()方法傳遞一個對象時,或使用load()、 get()、list()、iterate() 或scroll()方法獲得一個對象時, 該對象都將被加入到Session的內部緩存中。
當隨後flush()方法被調用時,對象的狀態會和資料庫取得同步。 如果你不希望此同步操作發生,或者你正處理大量對象、需要對有效管理內存時,你可以調用evict() 方法,從一級緩存中去掉這些對象及其集合。

Hibernate的查詢方式
Sql、Criteria,object comptosition
Hql:
1、 屬性查詢
2、 參數查詢、命名參數查詢
3、 關聯查詢
4、 分頁查詢
5、 統計函數

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

hibernate的開發步驟:
開發步驟
1)搭建好環境
引入hibernate最小的jar包
准備Hibernate.cfg.xml啟動配置文件
2)寫實體類(pojo)
3)為實體類寫映射文件"User.hbm.xml"
在hibernate.cfg.xml添加映射的實體
4)創建庫表
5)寫測試類
獲得Configuration
創建SessionFactory
打開Session
開啟事務
使用session操作數據
提交事務
關閉資源

熱點內容
榮耀v20升級存儲 發布:2024-07-27 09:20:19 瀏覽:484
安卓用什麼和電腦傳圖片 發布:2024-07-27 09:02:07 瀏覽:288
存儲過程就是 發布:2024-07-27 08:56:51 瀏覽:131
c語言高級試題 發布:2024-07-27 08:48:30 瀏覽:282
ip伺服器世界上有幾台 發布:2024-07-27 08:46:18 瀏覽:394
金立手機怎麼清理緩存 發布:2024-07-27 08:38:50 瀏覽:311
iphone文件夾不顯示 發布:2024-07-27 08:18:05 瀏覽:774
y510p固態硬碟做緩存 發布:2024-07-27 07:59:34 瀏覽:128
奶塊為什麼進伺服器會排隊 發布:2024-07-27 07:57:15 瀏覽:691
資料庫表標識 發布:2024-07-27 07:50:00 瀏覽:923