什么時候會遇到1+N的問題?
前提:hibernate默認表與表的關聯方法是fetch=”select”,不是fetch=”join”,這都是為了懶加載而準備的。
1)一對多() ,在1的這方,通過1條sql查找得到了1個對象,由于關聯的存在 ,那么又需要將這個對象關聯的集合取出,所以合集數量是n還要發出n條sql,于是本來的1條sql查詢變成了1 +n條 。
2)多對一 ,在多的這方,通過1條sql查詢得到了n個對象,由于關聯的存在,也會將這n個對象對應的1 方的對象取出, 于是本來的1條sql查詢變成了1 +n條 。
3)iterator 查詢時,一定先去緩存中找(1條sql查集合,只查出ID),在沒命中時,會再按ID到庫中逐一查找, 產生1+n條SQL
怎么解決1+N 問題? 1 )lazy=true, hibernate3開始已經默認是lazy=true了;lazy=true時不會立刻查詢關聯對象,只有當需要關聯對象(訪問其屬性,非id字段)時才會發生查詢動作。
2)使用二級緩存, 二級緩存的應用將不怕1+N 問題,因為即使第一次查詢很慢(未命中),以后查詢直接緩存命中也是很快的。剛好又利用了1+N 。
3) 當然你也可以設定fetch=”join”,一次關聯表全查出來,但失去了懶加載的特性。
//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.執行條件查詢時,iterate()方法具有著名的 “n+1”次查詢的問題,也就是說在第一次查詢時iterate方法會執行滿足條件的查詢結果數再加一次(n+1)的查詢。但是此問題只存在于第一次查詢時,在后面執行相同查詢時性能會得到極大的改善。此方法適合于查詢數據量較大的業務數據。但是注意:當數據量特別大時(比如流水線數據等)需要針對此持久化對象配置其具體的緩存策略,比如設置其存在于緩存中的最大記錄數、緩存存在的時間等參數,以避免系統將大量的數據同時裝載入內存中引起內存資源的迅速耗盡,反而降低系統的性能?。?!
新聞熱點
疑難解答