Hibernate優(yōu)化共15頁(yè)文檔_第1頁(yè)
Hibernate優(yōu)化共15頁(yè)文檔_第2頁(yè)
Hibernate優(yōu)化共15頁(yè)文檔_第3頁(yè)
Hibernate優(yōu)化共15頁(yè)文檔_第4頁(yè)
Hibernate優(yōu)化共15頁(yè)文檔_第5頁(yè)
已閱讀5頁(yè),還剩14頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、1. 抓取優(yōu)化抓取是指 Hibernate 如何在關(guān)聯(lián)關(guān)系之間進(jìn)行導(dǎo)航的時(shí)候, Hibernate 如何獲取關(guān)聯(lián)對(duì)象的策略,其主要定義了兩個(gè)方面:如何抓取和何時(shí)抓取。1)如何抓取。Hibernate3 主要有兩種抓取方式,分別應(yīng)用于對(duì)象關(guān)聯(lián)實(shí)例(many-to-one、one-to-one)和對(duì)象關(guān)聯(lián)集合(set、map等),總共是四種變種:JOIN抓取: 通過在SELECT語(yǔ)句中使用OUTER JOIN獲得對(duì)象的關(guān)聯(lián)實(shí)例或者關(guān)聯(lián)集合)SELECT?。毫硗獍l(fā)送一條SELECT語(yǔ)句來(lái)抓取當(dāng)前對(duì)象的關(guān)聯(lián)實(shí)體和集合在我的開發(fā)經(jīng)歷中,此處對(duì)性能的優(yōu)化是比較有限的,并不值得過多關(guān)注例:A. 應(yīng)用于對(duì)象關(guān)

2、聯(lián)實(shí)例(默認(rèn)是false )<many-to-one name="." outer-join="true/false/auto"./>B. 應(yīng)用于對(duì)象關(guān)聯(lián)集合(默認(rèn)是auto )<set name="." fetch="join/select" . ></set>2)何時(shí)抓取主要分為 延遲加載和立即抓取 ,默認(rèn)的情況下 Hibernate3 對(duì)對(duì)象關(guān)聯(lián) 實(shí)采用延遲加載, 普通屬性采用立即抓取 ,通過延遲加載和采用適當(dāng)?shù)淖ト×6龋c不采用優(yōu)化相 比往往可以將性能提升數(shù)倍。立即抓?。?/p>

3、 當(dāng)抓取宿主對(duì)象時(shí),同時(shí)抓取其關(guān)聯(lián)對(duì)象和關(guān)聯(lián)集以及屬性延遲加載:當(dāng)抓取宿主對(duì)象時(shí),并不抓取其關(guān)聯(lián)對(duì)象,而是當(dāng)對(duì)其對(duì)象進(jìn)行調(diào)用時(shí)才加載。例:A. 應(yīng)用于對(duì)象關(guān)聯(lián)實(shí)例(默認(rèn)是延遲加載)<many-to-one name="."lazy="true/false" ./>B. 應(yīng)用于對(duì)象關(guān)聯(lián)集合(默認(rèn)是延遲加載)<set name="." lazy="true/false" . ></set>對(duì)于延遲加載,需要注意的時(shí),對(duì)延遲對(duì)象的使用必須在 Session 關(guān)閉之前進(jìn)行, Hibern

4、ate 的 LazyInitalizationException 往往就是由于在 Session 的生命期外使用 了延遲加載的對(duì)象。當(dāng)我們進(jìn)行Web開發(fā)時(shí),可以使用OpenSessionInView模式,當(dāng)請(qǐng)求開始時(shí)打開session,當(dāng)請(qǐng)求響應(yīng)結(jié)束時(shí)才關(guān)閉session,不過,在使用OpenSessionInView 模式時(shí),需要注意如果響應(yīng)時(shí)間比較長(zhǎng)(業(yè)務(wù)比較復(fù)雜或者客戶端是低速網(wǎng)絡(luò)),將Session 資源(也就是數(shù)據(jù)庫(kù)的連接 )占用太久的話可以會(huì)導(dǎo)致資源耗盡。3)抓取粒度抓取粒度指的是對(duì)象在關(guān)聯(lián)關(guān)系之間被導(dǎo)航時(shí)一次預(yù)先加載的數(shù)量,Hibernate 程序的性能比較差往往就在于沒有對(duì)抓取

5、粒度仔細(xì)考慮, 當(dāng)加載一個(gè)列表并在列表中的每個(gè)對(duì)象中對(duì)其關(guān)聯(lián)進(jìn)行導(dǎo)航時(shí),往往導(dǎo)致N+1條SQL語(yǔ)句查詢。例:A. 應(yīng)用于對(duì)象關(guān)聯(lián)實(shí)例(默認(rèn)為 1),注意,對(duì)對(duì)象關(guān)聯(lián)實(shí)例的設(shè)置是在被關(guān)聯(lián)的對(duì)象之上的,譬如class UserGroup g;那么抓取粒度應(yīng)該在 Group 的配置文件之上,見下<class name="Group" table="group"batch-size="."></class>對(duì)該值并沒有一個(gè)約定俗成的值,根據(jù)情況而定,如果被關(guān)聯(lián)表數(shù)據(jù)比較少,則可以設(shè)置地小一些,3-20 ,如果比較大則可

6、以設(shè)到 30-50 ,注意的時(shí)候,并不是越多越好,當(dāng)其值超過 50 之后,對(duì)性能并沒有多大改善但卻無(wú)謂地消耗內(nèi)存假設(shè)有如下例子:List<User> users = query.list();如果有20個(gè)User,并對(duì)這20個(gè)User及其Group進(jìn)行遍歷,如果不設(shè)置 batch-size (即batch-size="1"),則在最糟糕的情況下,需要1 + 20條SQL語(yǔ)句,如果設(shè)置batch-size="10",則最好的情況下只需要1 + 2條SQL語(yǔ)句。B. 應(yīng)用于對(duì)象關(guān)聯(lián)集合(默認(rèn)為 1)<set name=".&quo

7、t; batch-size="" . ></set>2. 二級(jí)緩存Hibernate 對(duì)數(shù)據(jù)的緩存包括兩個(gè)級(jí): 一級(jí)緩存, 在 Session 的級(jí)別上進(jìn)行, 主要是對(duì)象緩存, 以其 id 為鍵保存對(duì)象, 在 Session 的生命期間存在; 二級(jí)緩存, 在 SessionFactory 的級(jí)別上進(jìn)行,有對(duì)象緩存和查詢緩存,查詢緩存以查詢條件為鍵保存查詢結(jié)果,在 SessionFactory 的生命期間存在。默認(rèn)地, Hibernate 只 啟用一級(jí)緩存,通過正確地使用二級(jí)緩存,往往可以獲得意想不到的性能。1)對(duì)象緩存:當(dāng)抓取一個(gè)對(duì)象之后, Hiberat

8、e 將其以 id 為鍵緩存起來(lái),當(dāng)下次碰到抓取 id 相同的對(duì)象時(shí),可以使用如下配置。方法 1:在緩存對(duì)象上配置<class .><cache useage="read-only/write/" regions="group" /></class>useage 表示使用什么類型的緩存,譬如只讀緩存、讀寫緩存等等(具體參見 Hibernate 參考指南),值得注意的時(shí),有部分緩存在 Hibernate 的實(shí)現(xiàn)中不支持讀寫緩存,譬如 JBossCache 在 Hibernate 的實(shí)現(xiàn)中只是一種只讀緩存,具體緩存實(shí)現(xiàn)對(duì)緩存

9、類型的支持情況,可以參見 org.hibernate.cache 包regions 表示緩存分塊,大部分的緩存實(shí)現(xiàn)往往對(duì)緩存進(jìn)行分塊,該部分是可選的,詳細(xì)參見各緩存實(shí)現(xiàn)。方法 2:在 hibernate.cfg.xml 中配置<cache class="." useage="." regions="."/>我認(rèn)為第二種更好,可以統(tǒng)一管理。2) 查詢緩存查詢時(shí)候?qū)⒉樵兘Y(jié)果以查詢條件為鍵保存起來(lái),需要配置如下A. 在 hibernate.cfg.xml 中配置(啟用查詢緩存)vproperty name="hiber

10、nate.cache.use_query_cache">true</property>(前面的屬性名可參見常量org.hibernate.cfg.Enviroment.USE_QUERY_CACHE )。B.程序query.setCacheable(true);query.setCacheRegions(.);需要注意的是 ,查詢緩存與對(duì)象緩存 要結(jié)合更有效 , 因?yàn)椴樵兙彺鎯H緩存查詢結(jié)果列表的主鍵數(shù)據(jù)一般情況下在開發(fā)中, 對(duì)一些比較穩(wěn)定而又被頻繁引用的數(shù)據(jù), 譬如數(shù)據(jù) 字典之類的,將其進(jìn)行二級(jí)緩存,對(duì)一些查詢條件和查詢數(shù)據(jù)變化不頻繁而又常常被使用的查詢,將其進(jìn)行二

11、級(jí)緩存 。由于二級(jí)緩存是放在內(nèi)存中,而且 Hibernate 的緩存不是弱引用緩存(WeekReference),所以注意不要將大塊的數(shù)據(jù)放入其中,否則可能會(huì)被內(nèi)存造成比較大的壓力。3. 批量數(shù)據(jù)操作當(dāng)進(jìn)行大批量數(shù)據(jù)操作(幾萬(wàn)甚至幾十幾百萬(wàn))時(shí),需要注意兩點(diǎn),一,批量提交,二,及時(shí)清除不需要的一級(jí)緩存數(shù)據(jù)1) 所謂的批量提交,就是不要頻繁使用session的flush,每一次進(jìn)行flush,Hibernate將P0數(shù)據(jù)于數(shù)據(jù)庫(kù)進(jìn)行同步,對(duì)于海量級(jí)數(shù)據(jù)操作來(lái)說(shuō)是性能災(zāi)難(同時(shí)提交幾千條數(shù)據(jù)和提交一條數(shù)據(jù) flush 一次性能差別可能會(huì)是幾十倍的差異)。一般將數(shù)據(jù)操作放在事務(wù)中,當(dāng)事務(wù)提交時(shí)Hib

12、ernate 自動(dòng)幫你進(jìn)行 flush 操作。2) 及時(shí)清除不需要的一級(jí)緩存數(shù)據(jù):由于Hibernate 默認(rèn)采用一級(jí)緩存,而在 session 的生命期間,所有數(shù)據(jù)抓取之后會(huì)放入一級(jí)緩存中,而當(dāng)數(shù)據(jù)規(guī)模比較龐大時(shí),抓取 到內(nèi)存中的數(shù)據(jù)會(huì)讓內(nèi)存壓力非常大,一般分批操作數(shù)據(jù),被一次操作之后將一級(jí)緩存清除,譬如session.clear(User.class)4. 雜項(xiàng)dynamic-insert , dynamic-update ,動(dòng)態(tài)插入和動(dòng)態(tài)更新, 指的是讓 Hibernate 插入數(shù)據(jù)時(shí)僅插入非空數(shù)據(jù),當(dāng)修改數(shù)據(jù)時(shí)只修改變化的數(shù)據(jù),譬如對(duì)于class User id usernamepas

13、sword如果 u.id=1, u.username="ayufox",u.password=null ,那么如果不設(shè)置動(dòng)態(tài)插入,則其 sql 語(yǔ)句是 insert into users(id, username, password) values (1, 'ayufox', ') ,如果設(shè)置則其 sql 語(yǔ)句是 insert into users(username) valeus('ayufox')在如上的情況下,如果修改 u.password='11' ,那么如果不設(shè)置動(dòng)態(tài)更新,則 sql 語(yǔ)句為 update u

14、sers set username='ayufox', password='11' where id = 1,如果設(shè)置則為 update user set password='11' where d = 1設(shè)置是在 class 的映射文件中,如下<class name="User" table="users" dynamic=insert="true/false" dynamic-update="true/false" .></class>該設(shè)

15、置對(duì)性能的提升比較有限Hibernate 優(yōu)化方案一、 批量修改和刪除在 Hibernate 2 中,如果需要對(duì)任何數(shù)據(jù)進(jìn)行修改和刪除操作,都需要先執(zhí)行查詢操作,在得到要修改或者刪除的數(shù)據(jù)后,再對(duì)該數(shù)據(jù)進(jìn)行相應(yīng)的操作處理。在數(shù)據(jù)量少的情況下采用這種處理方式?jīng)]有問題,但需要處理大量數(shù)據(jù)的時(shí)候就可能存在以下的問題:占用大量的內(nèi)存。需要多次執(zhí)行 update/delete 語(yǔ)句,而每次執(zhí)行只能處理一條數(shù)據(jù)。以上兩個(gè)問題的出現(xiàn)會(huì)嚴(yán)重影響系統(tǒng)的性能。因此,在Hiber nate 3中引入了用于批量更新或者刪除數(shù)據(jù)的HQL語(yǔ)句。這樣,開發(fā)人員就可以一次更新或者刪除多條記錄,而不用每次都一個(gè)一個(gè)地修改或者刪

16、除記錄了。如果要?jiǎng)h除所有的 User對(duì)象(也就是User對(duì)象所對(duì)應(yīng)表中的記錄),則可以直接使用下面的 HQL語(yǔ)句:delete User而在執(zhí)行這個(gè)HQL語(yǔ)句時(shí),需要調(diào)用 Query對(duì)象的executeUpdate()方法,具體的實(shí)例如下所示:String HQL="delete User"Query query=session.createQuery(HQL);int size=query.executeUpdate();采用這種方式進(jìn)行數(shù)據(jù)的修改和刪除時(shí)與直接使用JDBC的方式在性能上相差無(wú)幾,是推薦使用的正確方法。如果不能采用HQL 語(yǔ)句進(jìn)行大量數(shù)據(jù)的修改,也就是說(shuō)只

17、能使用取出再修改的方式時(shí),也會(huì)遇到批量插入時(shí)的內(nèi)存溢出問題,所以也要采用上面所提供的處理方法來(lái)進(jìn)行類似的處理。二、使用SQL執(zhí)行批量操作在進(jìn)行批量插入、修改和刪除操作時(shí),直接使用JDBC來(lái)執(zhí)行原生態(tài)的SQL語(yǔ)句無(wú)疑會(huì)獲得最佳的性能,這是因?yàn)樵谔幚淼倪^程中省略或者簡(jiǎn)化了以下處理內(nèi)容: HQL語(yǔ)句到SQL語(yǔ)句的轉(zhuǎn)換。 Java 對(duì)象的初始化。 Java 對(duì)象的緩存處理。但是在直接使用JDBC執(zhí)行SQL語(yǔ)句時(shí),有一個(gè)最重要的問題就是要處理緩存中的Java對(duì)象。因?yàn)橥ㄟ^這種底層方式對(duì)數(shù)據(jù)的修改將不能通知緩存去進(jìn)行相應(yīng)的更新操作,以保證緩存中的對(duì)象與數(shù)據(jù)庫(kù)中的數(shù)據(jù)是一致的。提升數(shù)據(jù)庫(kù)查詢的性能數(shù)據(jù)庫(kù)查詢

18、性能的提升也是涉及到開發(fā)中的各個(gè)階段,在開發(fā)中選用正確的查詢方法無(wú)疑是最基礎(chǔ)也最簡(jiǎn)單的。1、SQL語(yǔ)句的優(yōu)化使用正確的SQL語(yǔ)句可以在很大程度上提高系統(tǒng)的查詢性能。獲得同樣數(shù)據(jù)而采用不同方式的SQL語(yǔ)句在性能上的差距可能是十分巨大的。由于Hibernate是對(duì)JDBC的封裝,SQL語(yǔ)句的產(chǎn)生都是動(dòng)態(tài)由 Hibernate自動(dòng)完成的。Hibernate 產(chǎn)生SQL語(yǔ)句的方式有兩種:一種是通過開發(fā)人員編寫的HQL語(yǔ)句來(lái)生成,另一種是依據(jù)開發(fā)人員對(duì)關(guān)聯(lián)對(duì)象的訪問來(lái)自動(dòng)生成相應(yīng)的SQL語(yǔ)句。至于使用什么樣的SQL語(yǔ)句可以獲得更好的性能要依據(jù)數(shù)據(jù)庫(kù)的結(jié)構(gòu)以及所要獲取數(shù)據(jù)的具體情況來(lái)進(jìn)行處理。在確定了所要

19、執(zhí)行的SQL語(yǔ)句后,可以通過以下三個(gè)方面來(lái)影響Hibernate所生成的SQL語(yǔ)句:HQL語(yǔ)句的書寫方法。查詢時(shí)所使用的查詢方法。對(duì)象關(guān)聯(lián)時(shí)所使用的抓取策略。2 、使用正確的查詢方法一種是得到單個(gè)持久化對(duì)象的 get() 方法和 load() 方法,另一種是 Query 對(duì)象的 list() 方法和 iterator() 方在前面已經(jīng)介紹過,執(zhí)行數(shù)據(jù)查詢功能的基本方法有兩種:法。 在開發(fā)中應(yīng)該依據(jù)不同的情況選用正確的方法。get() 方法和 load() 方法的區(qū)別在于對(duì)二級(jí)緩存的使用上。load() 方法會(huì)使用二級(jí)緩存,而 get() 方法在一級(jí)緩存沒有找到的情況下會(huì)直接查詢數(shù)據(jù)庫(kù),不會(huì)去二

20、級(jí)緩存中查找。在使用中,對(duì)使用了二級(jí)緩存的對(duì)象進(jìn)行查詢時(shí)最好使用load() 方法,以充分利用二級(jí)緩存來(lái)提高檢索的效率。list() 方法和 iterator() 方法之間的區(qū)別可以從以下幾個(gè)方面來(lái)進(jìn)行比較。執(zhí)行的查詢不同list() 方法在執(zhí)行時(shí),是直接運(yùn)行查詢結(jié)果所需要的查詢語(yǔ)句,而 iterator() 方法則是先執(zhí)行得到對(duì)象 ID 的查詢,然后再根據(jù)每個(gè) ID 值去取得所要查詢的對(duì)象。因此, 對(duì)于list()方式的查詢通常只會(huì)執(zhí)行一個(gè)SQL語(yǔ)句,而對(duì)于iterator。方法的查詢則可能需要執(zhí)行N+1條SQL語(yǔ)句(N為結(jié)果集中的記錄數(shù))。iterator。方法只是可能執(zhí)行 N+1條數(shù)據(jù),

21、具體執(zhí)行SQL語(yǔ)句的數(shù)量取決于緩存的情況以及對(duì)結(jié)果集的訪問情況。緩存的使用list() 方法 只能使用二級(jí)緩存中的查詢緩存,而無(wú)法使用二級(jí)緩存對(duì)單個(gè)對(duì)象的緩存 (但是會(huì)把查詢出的對(duì)象放入二級(jí)緩存中 ) 。所以,除非重復(fù)執(zhí)行相同的查詢操作, 否則無(wú)法利用緩存的機(jī)制來(lái)提高查詢的效率。iterator() 方法則可以充分利用二級(jí)緩存,在根據(jù) ID 檢索對(duì)象的時(shí)候會(huì)首先到緩存中查找,只有在找不到的情況下才會(huì)執(zhí)行相應(yīng)的查詢語(yǔ)句。所以,緩存中對(duì)象的存在 與否會(huì)影響到SQL語(yǔ)句的執(zhí)行數(shù)量。對(duì)于結(jié)果集的處理方法不同list() 方法會(huì)一次獲得所有的結(jié)果集對(duì)象, 而且它會(huì)依據(jù)查詢的結(jié)果初始化所有的結(jié)果集對(duì)象。

22、這在結(jié)果集非常大的時(shí)候必然會(huì)占據(jù)非常多的內(nèi)存, 甚至?xí)斐蓛?nèi)存溢出 情況的發(fā)生。iterator() 方法在執(zhí)行時(shí)不會(huì)一次初始化所有的對(duì)象,而是根據(jù)對(duì)結(jié)果集的訪問情況來(lái)初始化對(duì)象。因此在訪問中可以控制緩存中對(duì)象的數(shù)量,以避 免占用過多緩存, 導(dǎo)致內(nèi)存溢出情況的發(fā)生。使用 iterator() 方法的另外一個(gè)好處是,如果只需要結(jié)果集中的部分記錄,那么沒有被用到的結(jié)果對(duì)象根本 不會(huì)被初始化。所以,對(duì)結(jié)果集的訪 問情況也是調(diào)用iterator。方法時(shí)執(zhí)行數(shù)據(jù)庫(kù)SQL語(yǔ)句多少的一個(gè)因素。所以,在使用 Query 對(duì)象執(zhí)行數(shù)據(jù)查詢時(shí)應(yīng)該從以上幾個(gè)方面去考慮使用何種方法來(lái)執(zhí)行數(shù)據(jù)庫(kù)的查詢操作。四、 使用正

23、確的抓取策略所謂抓取策略(fetching strategy)是指當(dāng)應(yīng)用程序需要利用關(guān)聯(lián)關(guān)系進(jìn)行對(duì)象獲取的時(shí)候,Hibernate獲取關(guān)聯(lián)對(duì)象的策略。抓取策略可以在0/R映射的元數(shù)據(jù)中聲明,也可以在特定的HQL或條件查詢中聲明。Hibernate 3 定義了以下幾種抓取策略。連接抓取 (Join fetching)連接抓取是指Hibernate在獲得關(guān)聯(lián)對(duì)象時(shí)會(huì)在 SELECT語(yǔ)句中使用外連接的方式來(lái)獲得關(guān)聯(lián)對(duì)象。查詢抓取 (Select fetching)查詢抓取是指Hibernate通過另外一條SELECTS句來(lái)抓取當(dāng)前對(duì)象的關(guān)聯(lián)對(duì)象的方式。這也是通過外鍵的方式來(lái)執(zhí)行數(shù)據(jù)庫(kù)的查詢。與連接抓

24、取的區(qū)別在于,通常情況下這個(gè)SELECT吾句不是立即執(zhí)行的,而是在訪問到關(guān)聯(lián)對(duì)象的時(shí)候才會(huì)執(zhí)行。子查詢抓取 (Subselect fetching)子查詢抓取也是指 Hibernate通過另外一條SELECT吾句來(lái)抓取當(dāng)前對(duì)象的關(guān)聯(lián)對(duì)象的方式。與查詢抓取的區(qū)別在于它所采用的SELECT吾句的方式為子查詢, 而不是通過外連接。批量抓取 (Batch fetching)批量抓取是對(duì)查詢抓取的優(yōu)化,它會(huì)依據(jù)主鍵或者外鍵的列表來(lái)通過單條SELECT吾句實(shí)現(xiàn)管理對(duì)象的批量抓取。以上介紹的是 Hibernate 3 所提供的抓取策略,也就是抓取關(guān)聯(lián)對(duì)象的手段。為了提升系統(tǒng)的性能,在抓取關(guān)聯(lián)對(duì)象的時(shí)機(jī)上,還

25、有以下一些選擇。立即抓取 (Immediate fetching)立即抓取是指宿主對(duì)象被加載時(shí),它所關(guān)聯(lián)的對(duì)象也會(huì)被立即加載。延遲集合抓取 (Lazy collection fetching)延遲集合抓取是指在加載宿主對(duì)象時(shí),并不立即加載它所關(guān)聯(lián)的對(duì)象,而是到應(yīng)用程序訪問關(guān)聯(lián)對(duì)象的時(shí)候才抓取關(guān)聯(lián)對(duì)象。這是集合關(guān)聯(lián)對(duì)象的默認(rèn)行為。延遲代理抓取 (Lazy proxy fetching)延遲代理抓取是指在返回單值關(guān)聯(lián)對(duì)象的情況下,并不在對(duì)其進(jìn)行 get 操作時(shí)抓取,而是直到調(diào)用其某個(gè)方法的時(shí)候才會(huì)抓取這個(gè)對(duì)象。延遲屬性加載 (Lazy attribute fetching)延遲屬性加載是指在關(guān)聯(lián)對(duì)

26、象被訪問的時(shí)候才進(jìn)行關(guān)聯(lián)對(duì)象的抓取。介紹了 Hibernate 所提供的關(guān)聯(lián)對(duì)象的抓取方法和抓取時(shí)機(jī), 這兩個(gè)方面的因素都會(huì)影響 Hibernate 的抓取行為, 最重要的是要清楚這兩方面的影響是不同的, 不要將這 兩個(gè)因素混淆,在開發(fā)中要結(jié)合實(shí)際情況選用正確的抓取策略和合適的抓取時(shí)機(jī)。抓取時(shí)機(jī)的選擇在 Hibernate 3 中,對(duì)于集合類型的關(guān)聯(lián)在默認(rèn)情況下會(huì)使用延遲集合加載的抓取時(shí)機(jī),而對(duì)于返回單值類型的關(guān)聯(lián)在默認(rèn)情況下會(huì)使用延遲代理抓取的抓取時(shí)機(jī)。對(duì)于立即抓取在開發(fā)中很少被用到,因?yàn)檫@很可能會(huì)造成不必要的數(shù)據(jù)庫(kù)操作,從而影響系統(tǒng)的性能。當(dāng)宿主對(duì)象和關(guān)聯(lián)對(duì)象總是被同時(shí)訪問的時(shí)候才有可能會(huì)

27、 用到這 種抓取時(shí)機(jī)。另外,使用立即連接抓取可以通過外連接來(lái)減少查詢SQL語(yǔ)句的數(shù)量,所以,也會(huì)在某些特殊的情況下使用。然而, 延遲加載又會(huì)面臨另外一個(gè)問題, 如果在 Session 關(guān)閉前關(guān)聯(lián)對(duì)象沒有被實(shí)例化, 那么在訪問關(guān)聯(lián)對(duì)象的時(shí)候就會(huì)拋出異常。 處理的方法就是在事務(wù)提交之前就完 成對(duì)關(guān)聯(lián)對(duì)象的訪問。所以, 在通常情況下都會(huì)使用延遲的方式來(lái)抓取關(guān)聯(lián)的對(duì)象。 因?yàn)槊總€(gè)立即抓取都會(huì)導(dǎo)致關(guān)聯(lián)對(duì)象的立即實(shí)例化, 太多的立即抓取關(guān)聯(lián)會(huì)導(dǎo)致大量的對(duì)象被實(shí)例化, 從而 占用過多的內(nèi)存資源。抓取策略的選取對(duì)于抓取策略的選取將影響到抓取關(guān)聯(lián)對(duì)象的方式,也就是抓取關(guān)聯(lián)對(duì)象時(shí)所執(zhí)行的SQL語(yǔ)句。這就要根據(jù)實(shí)際

28、的業(yè)務(wù)需求、數(shù)據(jù)的數(shù)量以及數(shù)據(jù)庫(kù)的結(jié)構(gòu)來(lái)進(jìn)行選擇了。在這里需要注意的是,通常情況下都會(huì)在執(zhí)行查詢的時(shí)候針對(duì)每個(gè)查詢來(lái)指定對(duì)其合適的抓取策略。指定抓取策略的方法如下所示:User user = (User) session.createCriteria(User.class).setFetchMode("permissions", FetchMode.JOIN).add( Restrictions.idEq(userId) ).uniqueResult();五、 查詢性能提升小結(jié)在本小節(jié)中介紹了查詢性能提升的方法,關(guān)鍵是如何通過優(yōu)化 SQL語(yǔ)句來(lái)提升系統(tǒng)的查詢性能。 查詢方法

29、和抓取策略的影響也是通過執(zhí)行查詢方式和SQL語(yǔ)句的多少來(lái)改變系統(tǒng)的性能的。這些都屬于開發(fā)人員所應(yīng)該掌握的基本技能,避免由于開發(fā)不當(dāng)而導(dǎo)致系統(tǒng)性能的低下。在性能調(diào)整中,除了前面介紹的執(zhí)行 SQL語(yǔ)句的因素外,對(duì)于緩存的使用也會(huì)影響系統(tǒng)的性能。通常來(lái)說(shuō),緩存的使用會(huì)增加系統(tǒng)查詢的性能,而降低系統(tǒng)增力口、修改和刪除操作的性能 (因?yàn)橐M(jìn)行緩存的同步處理 )。所以,開發(fā)人員應(yīng)該能夠正確地使用有效的緩存來(lái)提高數(shù)據(jù)查詢的性能,而要避免濫用緩存而導(dǎo)致的系統(tǒng)性能變低。在采用緩存的時(shí)候也應(yīng)該注意調(diào)整自己的檢索策略和查詢方法,這三者配合起來(lái)才可以達(dá)到最優(yōu)的性能。另外,事務(wù)的使用策略也會(huì)影響到系統(tǒng)的性能。選取正確的

30、事務(wù)隔離級(jí)別以及使用。Hibernate 中二級(jí)緩存的配置和使用(一) Hibernate的二級(jí)緩存策略的一般過程如下:1)條件查詢的時(shí)候,總是發(fā)出一條 select * from table_name where.(選擇所有字段)這樣的SQL語(yǔ)句查詢數(shù)據(jù)庫(kù), 一次獲得所有的數(shù)據(jù)對(duì)象。2)把獲得的所有數(shù)據(jù)對(duì)象根據(jù) ID 放入到第二級(jí)緩存中。3)當(dāng) Hibernate 根據(jù) ID 訪問數(shù)據(jù)對(duì)象的時(shí)候,首先從 Session 一級(jí)緩存中查;查不到,如果配置了二級(jí)緩存,那么從二級(jí)緩存中查;查不到,再查詢數(shù)據(jù)庫(kù),把結(jié)果按照ID 放入到緩存。4)刪除、更新、增加數(shù)據(jù)的時(shí)候,同時(shí)更新緩存。Hibernat

31、e 的二級(jí)緩存策略,是針對(duì)于 ID 查詢的緩存策略,對(duì)于條件查詢則毫無(wú)作用。 為此, Hibernate 提供了針對(duì)條件查詢的 Query Cache 。(二)什么樣的數(shù)據(jù)適合存放到第二級(jí)緩存中?1 很少被修改的數(shù)據(jù)2 不是很重要的數(shù)據(jù),允許出現(xiàn)偶爾并發(fā)的數(shù)據(jù)3 不會(huì)被并發(fā)訪問的數(shù)據(jù)4 參考數(shù)據(jù) , 指的是供應(yīng)用參考的常量數(shù)據(jù),它的實(shí)例數(shù)目有限,它的實(shí)例會(huì)被許多其他類的實(shí)例引用,實(shí)例極少或者從來(lái)不會(huì)被修改。(三)不適合存放到第二級(jí)緩存的數(shù)據(jù)?1 經(jīng)常被修改的數(shù)據(jù)2 財(cái)務(wù)數(shù)據(jù),絕對(duì)不允許出現(xiàn)并發(fā)3 與其他應(yīng)用共享的數(shù)據(jù)。實(shí)踐部分:使用EhCache配置二級(jí)緩存:配置準(zhǔn)備:1)把 ehcache-

32、1.2.3.jar 加入到當(dāng)前應(yīng)用的 classpath 中。2)在hibernate.cfg.xml文件中加入 EhCache緩存插件的提供類。1. <!- 配置緩存插件->2. <propertyname="vider_class">3. org.hibernate.cache.EhCacheProvider4. </property>3)挎貝 ehcache.xml 文件到類路徑 ( 項(xiàng)目工程的 src 目錄下 ),這個(gè)文件在 Hibernate 安裝目錄的 etc 下。配置步驟:Hiberna

33、te 允許在類和集合的粒度上設(shè)置第二級(jí)緩存。在映射文件中,class和set元素都有一個(gè)cache子元素,這個(gè)子元素用來(lái)配置二級(jí)緩存。示例:以 category( 產(chǎn)品類別 ) 和 product( 產(chǎn)品 ) 的映射為例:1) 修改要配置緩存的那個(gè)持久化類的對(duì)象關(guān)系映射文件:1.Category.hbm.xml<?xml version="1.0" encoding="utf-8"?>Hibernate 允許在類和集合的粒度上設(shè)置第二級(jí)緩存。在映射文件中,class和set元素都有一個(gè)cache子元素,這個(gè)子元素用來(lái)配置二級(jí)緩存。Hibern

34、ate 允許在類和集合的粒度上設(shè)置第二級(jí)緩存。在映射文件中,class和set元素都有一個(gè)cache子元素,這個(gè)子元素用來(lái)配置二級(jí)緩存。2.<!DOCTYPE hibernate-mapping PUBLIC "-/Hibernate/HibernateMapping DTD 3.0/EN"Hibernate 允許在類和集合的粒度上設(shè)置第二級(jí)緩存。在映射文件中,class和set元素都有一個(gè)cache子元素,這個(gè)子元素用來(lái)配置二級(jí)緩存。3."http:/hibernate.sourceforge/hibernate-mapping-3.0.dtd"

35、>Hibernate 允許在類和集合的粒度上設(shè)置第二級(jí)緩存。在映射文件中,class和set元素都有一個(gè)cache子元素,這個(gè)子元素用來(lái)配置二級(jí)緩存。Hibernate 允許在類和集合的粒度上設(shè)置第二級(jí)緩存。在映射文件中,class和set元素都有一個(gè)cache子元素,這個(gè)子元素用來(lái)配置二級(jí)緩存。4.<hibernate-mapping>5.<class name="org.qiujy.domain.cachedemo.Category"table="categories">6.配置緩存 , 必須緊跟在 class 元素后面

36、7.對(duì)緩存中的 Category 對(duì)象采用讀寫型的并發(fā)訪問策略8.<cache usage="read-write"/>9.<id name="id" type="java.lang.Long">10.<column name="id" />11.<generator class="native" />12.</id>13.!-配置版本號(hào) , 必須緊跟在 id 元素后面14.<version name="version&

37、quot; column="version" type="java.lang.Long"/>15.<property name="name" type="java.lang.String">16.<column name="name" length="32" not-null="true"/>17.</property>18.<property name="description" typ

38、e="java.lang.String">19.<column name="description" length="255"/>20.</property>21.<set name="products" table="products"cascade="all" inverse="true">22.!-Hibernate 只會(huì)緩存對(duì)象的簡(jiǎn)單屬性的值23.要緩存集合屬性,必須在集合元素中也加入cache子元素24.

39、而Hibernate僅僅是把與當(dāng)前持久對(duì)象關(guān)聯(lián)的對(duì)象的OID存放到緩存中。25.如果希望把整個(gè)關(guān)聯(lián)的對(duì)象的所有數(shù)據(jù)都存入緩存26.則要在相應(yīng)關(guān)聯(lián)的對(duì)象的映射文件中配置cache 元素27.<cache usage="read-write"/>28.<key column="categoryId" not-null="true"/>29.<one-to-many class="org.qiujy.domain.cachedemo.Product"/>30.</set>3

40、1.</class>32.</hibernate-mapping>Hibernate 允許在類和集合的粒度上設(shè)置第二級(jí)緩存。在映射文件中,class和set元素都有一個(gè)cache子元素,這個(gè)子元素用來(lái)配置二級(jí)緩存。Hibernate 允許在類和集合的粒度上設(shè)置第二級(jí)緩存。在映射文件中,class和set元素都有一個(gè)cache子元素,這個(gè)子元素用來(lái)配置二級(jí)緩存。Product.hbm.xmlHibernate 允許在類和集合的粒度上設(shè)置第二級(jí)緩存。在映射文件中,class和set元素都有一個(gè)cache子元素,這個(gè)子元素用來(lái)配置二級(jí)緩存。Hibernate 允許在類和集合的

41、粒度上設(shè)置第二級(jí)緩存。在映射文件中,class和set元素都有一個(gè)cache子元素,這個(gè)子元素用來(lái)配置二級(jí)緩存。1.<?xml version="1.0"encoding="utf-8"?>2.<!DOCTYPE hibernate-mapping PUBLIC "-/Hibernate/HibernateMapping DTD 3.0/EN"Hibernate 允許在類和集合的粒度上設(shè)置第二級(jí)緩存。在映射文件中,class和set元素都有一個(gè)cache子元素,這個(gè)子元素用來(lái)配置二級(jí)緩存。3."http:/

42、hibernate.sourceforge/hibernate-mapping-3.0.dtd">4.<hibernate-mapping>5.<class name="org.qiujy.domain.cachedemo.Product"table="products">6.<cache usage="read-write"/>7.<idname="id" type="java.lang.Long">8.<column na

43、me="id" />9.<generator class="native" />10.</id>11.<!-配置版本號(hào) , 必須緊跟在 id 元素后面 ->12.<version name="version" column="version" type="java.lang.Long"/>13.<property name="name" type="java.lang.String">14.

44、<column name="name" length="32" not-null="true"/>15.</property>16.<property name="description" type="java.lang.String">17.<column name="description" length="255"/>18.</property>19.<property name=&q

45、uot;unitCost" type="java.lang.Double">20.<column name="unitCost" />21.</property>22.<property name="pubTime" type="java.util.Date">23.<column name="pubTime" not-null="true"/>24.</property>25.<many-to

46、-one name="category"26.column="categoryId"27.class="org.qiujy.domain.cachedemo.Category"28.cascade="save-update"29.not-null="true">30.</many-to-one>31.</class>32.</hibernate-mapping>2) 編輯 ehcache.xml 文件:1.<ehcache>2.<dis

47、kStore path="c:ehcache"/>3.<defaultCache4.maxElementsInMemory="10000"5.eternal="false"6.timeToIdleSeconds="120"7.timeToLiveSeconds="120"8.overflowToDisk="true"9.<!- 設(shè)置 Category 類的緩存的數(shù)據(jù)過期策略->10.<cache name="org.qiujy.doma

48、in.cachedemo.Category"11.maxElementsInMemory="100"12.eternal="true"13.timeToIdleSeconds="0"14.timeToLiveSeconds="0"15.overflowToDisk="false"16.<!-設(shè)置 Category 類的 products 集合的緩存的數(shù)據(jù)過期策略17.<cachename="org.qiujy.domain.cachedemo.Category.p

49、roducts"18.maxElementsInMemory="500"19.eternal="false"20.timeToIdleSeconds="300"21.timeToLiveSeconds="600"22.overflowToDisk="true"23.<cachename="org.qiujy.domain.cachedemo.Product"24.maxElementsInMemory="500"25.eternal=&qu

50、ot;false"26.timeToIdleSeconds="300"27.timeToLiveSeconds="600"28.overflowToDisk="true"29.</ehcache>在 Spring 托管的 Hibernate 中使用二級(jí)緩存1 在 spring 的配置文件中, hibernate 部分加入 xml 代碼 org.hibernate.cache.EhCacheProvider true2. 為HBM表設(shè)置cache策略xml代碼3 .在DAO中,調(diào)用find 方法查詢之前,設(shè)置使用緩

51、存 Java代碼getHibernateTemplate().setCacheQueries(true);補(bǔ)充: 如果不設(shè)置“查詢緩存”,那么 hibernate只會(huì)緩存使用 load() 方法獲得的單個(gè)持久化對(duì)象,如果想緩存使用 findall() 、list() 、 Iterator() 、createCriteria()、createQuery() 等方法獲得的數(shù)據(jù)結(jié)果集的話,就需要設(shè)置 hibernate.cache.use_query_cache true 才行。hibernate1. 在數(shù)據(jù)庫(kù)中條件查詢速度很慢的時(shí)候,如何優(yōu)化 ?(1). 建索引(2) . 減少表之間的關(guān)聯(lián)(3)

52、. 優(yōu)化 sql ,盡量讓 sql 很快定位數(shù)據(jù),不要讓 sql 做全表查詢,應(yīng)該走索引 , 把數(shù)據(jù)量大的表排在前面(4) . 簡(jiǎn)化查詢字段,沒用的字段不要,已經(jīng)對(duì)返回結(jié)果的控制,盡量返回少量數(shù)據(jù)2. 在 hibernate 中進(jìn)行多表查詢 ,每個(gè)表中各取幾個(gè)字段 ,也就是說(shuō)查詢出來(lái)的結(jié)果集并沒有一個(gè)實(shí)體類與之對(duì)應(yīng) ,如何解決這個(gè)問題 ?解決方案一,按照 Object 數(shù)據(jù)取出數(shù)據(jù),然后自己組 bean解決方案二,對(duì)每個(gè)表的 bean 寫構(gòu)造函數(shù),比如表一要查出 field1,field2 兩個(gè)字段,那么有一個(gè)構(gòu)造函數(shù)就是 Bean(type1 filed1,type2 field2) ,然后

53、在 hql 里面就可 以直接生成這個(gè) bean 了。具體怎么用請(qǐng)看相關(guān)文檔,我說(shuō)的不是很清楚。hibernate 的核心類是什么,它們的相互關(guān)系是什么?重要的方法是什么 ?Configuration 接口:配置 Hibernate ,根據(jù)其啟動(dòng) hibernate ,創(chuàng)建 SessionFactory 對(duì)象;SessionFactory 接口:初始化 Hibernate ,充當(dāng)數(shù)據(jù)存儲(chǔ)源的代理,創(chuàng)建session 對(duì)象, sessionFactory 是線程安全的,意味著它的同一個(gè)實(shí)例可以被應(yīng) 用的多個(gè)線程共享,是重量級(jí)、二級(jí)緩存;第 10 頁(yè)Session 接口:負(fù)責(zé)保存、更新、刪除、加載和

54、查詢對(duì)象,是線程不安全的, 避免多個(gè)線程共享同一個(gè) session ,是輕量級(jí)、一級(jí)緩存;Transaction 接口:管理事務(wù);Query 和 Criteria 接口:執(zhí)行數(shù)據(jù)庫(kù)的查詢。Session 如下方法Save/ load/Update/Delete/get/saveOrUpdate/deleteAllQuery q=CreateQuery( “from Customer where customerName=:customerName ”)beginTransactioncloseTransactionCommit()優(yōu)化 hibernate 性能的幾點(diǎn)建議1、針對(duì)oracle數(shù)據(jù)

55、庫(kù)而言,F(xiàn)etch Size 是設(shè)定JDBC的Statement讀取數(shù)據(jù)的時(shí)候每次從數(shù)據(jù)庫(kù)中取出的記錄條數(shù),一般設(shè)置為30、50、100。Oracle數(shù)據(jù)庫(kù)的JDBC驅(qū)動(dòng)默認(rèn) 的 Fetch Size=15 ,設(shè)置 Fetch Size 設(shè)置為: 30、 50,性能會(huì)有明顯提升,如果繼續(xù)增大,超出 100,性能提升不明顯,反而會(huì)消耗內(nèi)存。即在 hibernate 配制文件中進(jìn)行配制:Xml代碼1 v propertyname= hibernateProperties>2 v props >3 v propkey=”hibernate.dialect”> org.hiberna

56、te.dialect.Oracle9Dialectv /prop >4 v propkey=”hibernate.show_sql ”> false v /prop >when the JVM starts upCreate/update the database tables automatically> update v /prop >->6 v prop key=”hibernate.hbm2ddl.autoTurn batching off for bettererror messages under PostgreSQL8 v propkey=”h

57、ibernate.jdbc.batch_size”>100v/prop>->9 v propkey=”hibernate.jdbc.batch_size”>50v/prop>10 v/props >Xml代碼1. 1 vpropertyname=”hibernateProperties ”>第 11 頁(yè)2.2< props>3.3v propkey=”hibernate.dialect ”>org.hibernate.dialect.Oracle9Dialectv /prop >4.4v propkey=”hibernate.s

58、how_sql ”>falsev /prop >5.5v !-Create/updatethe databasetables automaticallywhenthe JVM startsup6.6v propkey=”hibernate.hbm2ddl.auto”>update v /prop >->7.7v !-Turnbatching off for bettererror messagesunderPostgreSQL8.8v propkey=”hibernate.jdbc.batch_size”> 100v /prop >->9.9v

59、propkey=”hibernate.jdbc.batch_size”> 50 v /prop >10.10v /props >11.< /property >Fetch Size 設(shè)的越大,讀數(shù)據(jù)庫(kù)的次數(shù)越少,速度越快; Fetch Size 越小,讀數(shù)據(jù)庫(kù)的次數(shù)越多,速度越慢。2、 如果是超大的系統(tǒng),建議生成htm 文件。加快頁(yè)面提升速度。3、不要把所有的責(zé)任推在 hibernate 上,對(duì)代碼進(jìn)行重構(gòu),減少對(duì)數(shù)據(jù)庫(kù)的操作,盡量避免在數(shù)據(jù)庫(kù)查詢時(shí)使用 in 操作,以及避免遞歸查詢操作,代碼質(zhì)量、系統(tǒng)設(shè)計(jì)的合 理性決定系統(tǒng)性能的高低。4、 對(duì)大數(shù)據(jù)量查詢時(shí),慎用 list() 或者 iterator() 返回查詢結(jié)果,(1) . 使用 List() 返回結(jié)果時(shí), Hibernate 會(huì)所有查詢結(jié)果初始化為持久化對(duì)象,結(jié)果集較大時(shí),會(huì)占用很多的處理時(shí)間。(2) . 而使用 iterator() 返回結(jié)果時(shí),在每次調(diào)用 iterator.next() 返回對(duì)象并使用對(duì)象時(shí), Hibernate 才調(diào)用查詢將對(duì)應(yīng)的對(duì)象初始 化,對(duì)于大數(shù)據(jù)量時(shí),每調(diào)用一次查詢都會(huì)花費(fèi)較多的時(shí)間。當(dāng)結(jié)果集較大,但是含有較大量相同的數(shù)據(jù),或者結(jié)果集不是全部都會(huì)使用時(shí),使用iterator() 才有優(yōu)勢(shì)。5、 在一對(duì)多

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論