什么時(shí)候會(huì)遇到1+N的問題?
前提:hibernate默認(rèn)表與表的關(guān)聯(lián)方法是fetch=”select”,不是fetch=”join”,這都是為了懶加載而準(zhǔn)備的。
1)一對(duì)多() ,在1的這方,通過1條sql查找得到了1個(gè)對(duì)象,由于關(guān)聯(lián)的存在 ,那么又需要將這個(gè)對(duì)象關(guān)聯(lián)的集合取出,所以合集數(shù)量是n還要發(fā)出n條sql,于是本來的1條sql查詢變成了1 +n條 。
2)多對(duì)一 ,在多的這方,通過1條sql查詢得到了n個(gè)對(duì)象,由于關(guān)聯(lián)的存在,也會(huì)將這n個(gè)對(duì)象對(duì)應(yīng)的1 方的對(duì)象取出, 于是本來的1條sql查詢變成了1 +n條 。
3)iterator 查詢時(shí),一定先去緩存中找(1條sql查集合,只查出ID),在沒命中時(shí),會(huì)再按ID到庫中逐一查找, 產(chǎn)生1+n條SQL
怎么解決1+N 問題? 1 )lazy=true, hibernate3開始已經(jīng)默認(rèn)是lazy=true了;lazy=true時(shí)不會(huì)立刻查詢關(guān)聯(lián)對(duì)象,只有當(dāng)需要關(guān)聯(lián)對(duì)象(訪問其屬性,非id字段)時(shí)才會(huì)發(fā)生查詢動(dòng)作。
2)使用二級(jí)緩存, 二級(jí)緩存的應(yīng)用將不怕1+N 問題,因?yàn)榧词沟谝淮尾樵兒苈ㄎ疵校院蟛樵冎苯泳彺婷幸彩呛芸斓摹偤糜掷昧?+N 。
3) 當(dāng)然你也可以設(shè)定fetch=”join”,一次關(guān)聯(lián)表全查出來,但失去了懶加載的特性。
//join fetch @Test public void test1_N3(){ session session=sf.getCurrentSession(); session.beginTransaction(); //List<Topic> topics=(List<Topic>)session.createCriteria(Topic.class).list(); List<Topic> topics=(List<Topic>)session.createQuery("from Topic t left join fetch t.category c").list(); for (Topic t:topics) { System.out.執(zhí)行條件查詢時(shí),iterate()方法具有著名的 “n+1”次查詢的問題,也就是說在第一次查詢時(shí)iterate方法會(huì)執(zhí)行滿足條件的查詢結(jié)果數(shù)再加一次(n+1)的查詢。但是此問題只存在于第一次查詢時(shí),在后面執(zhí)行相同查詢時(shí)性能會(huì)得到極大的改善。此方法適合于查詢數(shù)據(jù)量較大的業(yè)務(wù)數(shù)據(jù)。但是注意:當(dāng)數(shù)據(jù)量特別大時(shí)(比如流水線數(shù)據(jù)等)需要針對(duì)此持久化對(duì)象配置其具體的緩存策略,比如設(shè)置其存在于緩存中的最大記錄數(shù)、緩存存在的時(shí)間等參數(shù),以避免系統(tǒng)將大量的數(shù)據(jù)同時(shí)裝載入內(nèi)存中引起內(nèi)存資源的迅速耗盡,反而降低系統(tǒng)的性能!!!
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注