心得14-hibernate的优化2-抓取(fetch)
?在HQL語句中使用抓取連接查詢,通過寫一條left join fetch 語句把相關(guān)聯(lián)的兩個實(shí)體的數(shù)據(jù)一次性從數(shù)據(jù)庫中加載上來。這樣可以在特定情況下(同時需要使用到這兩個實(shí)體的數(shù)據(jù))減少SQL的數(shù)量來提高查詢效率。通過配置“抓取策略”來直接影響session的get()和load()方法的查詢效果。
1.單端關(guān)聯(lián)<many-to-one><one-to-one>上的抓取策略。
?? 可以給單端關(guān)聯(lián)的映射元素添加fetch屬性。fetch屬性有2個可選值.
? select:作為默認(rèn)值,它的策略是當(dāng)需要使用到關(guān)聯(lián)對象的數(shù)據(jù)時,另外單獨(dú)發(fā)送一條select語句抓取當(dāng)前對象的關(guān)聯(lián)對象的數(shù)據(jù)。即延遲加載。
??join:它的策略是在同一條select語句使用連接來獲得對象的數(shù)據(jù)和它關(guān)聯(lián)對象的數(shù)據(jù),此時關(guān)聯(lián)對象的延遲加載失效。
2.集合屬性上的抓取策略
在集合屬性的映射元素上可以添加fetch屬性,它有3個可選值。
?select:作為默認(rèn)值,它的策略是當(dāng)需要使用所關(guān)聯(lián)集合的數(shù)據(jù)時,另外單獨(dú)發(fā)送一條select語句抓取當(dāng)前對象的關(guān)聯(lián)集合,即延遲加載。
join:在同一條select語句使用連接來獲得對方的關(guān)聯(lián)集合。此時關(guān)聯(lián)集合上的lazy會失效。
subselect:另外發(fā)送一條查詢語句(或子查詢語句)抓取在前面查詢到的所有實(shí)體對象的關(guān)聯(lián)集合。這個策略對HQL的查詢也起作用。當(dāng)fetch為join時,執(zhí)行左外連接,這個時候,在加載Customer時,Customer所對應(yīng)的Order值全部被加載到緩存中,如果Order中沒有大數(shù)據(jù),這個策略是一個不錯的選擇。當(dāng)fetch為subselect時,針對in有效,如果為select時,from Customer where id in(1,2,3),hibernate會把ID取出來,逐一的去取Order的值,效率比較低。這個時候subselect效率比較高,不管in里含有多少數(shù)據(jù),在查詢Order是,只會發(fā)出一條sql語句。
把<set>集合中batch-size設(shè)置為一個比較合適的數(shù)值時也相當(dāng)于fetch為subselect,你可以根據(jù)項(xiàng)目的因素來選擇發(fā)出sql語句的次數(shù)。HQL總是忽略映射文件中設(shè)置的預(yù)先抓取策略,即在HQL中使用預(yù)先抓取時,必須顯示指明fetch關(guān)鍵字。然而不同的是,QBC則不會忽略映射文件中的預(yù)先抓取策略。
在實(shí)踐開發(fā)項(xiàng)目過程中,不僅需要根據(jù)實(shí)際情況選擇合適的抓取策略,而且需要通過不斷的測試來驗(yàn)證這個策略是不是最有效率的。
關(guān)聯(lián)級別檢索策略
3.? 案例分析
映射文件:
<set name="ord" table="orders" lazy="false" batch-size="2">
????????? <key column="cid"/>
????????? <one-to-many class="Orders"/>?
??????? </set>
測試:
?? //如果不設(shè)置fetch="join";默認(rèn)的是fetch="select",就是會出現(xiàn)兩條sql語句,設(shè)置了抓取會先抓取到所以相關(guān)聯(lián)的數(shù)據(jù),用的時候直接用,不再從數(shù)據(jù)庫中獲取
?? @Test
?? publicvoid testFetch(){
?????
????? Session session = HibernateUtil.getSession();
????? Customer cus = (Customer) session.get(Customer.class,3);
?????
????? //下面的語句也會在sql語句后一下輸出
????? System.out.println(cus.getCname());
?????
????? Set<Orders> orders =? cus.getOrd();
????? System.err.println(orders.size());
?????
????? HibernateUtil.close();
?? }
?
?? //測試fetch="subselect" 和 batch-size="2";兩者任選其一
?? @Test
?? publicvoid testSubselect(){
?????
????? Session session = HibernateUtil.getSession();
????? List<Customer> cus = session.createQuery("from Customer c where c.id in(1,2,3)").list();
????? for(Customer c : cus){?????
??????? System.err.println(c.getCname());
????? }
?????
????? HibernateUtil.close();
?? }
映射文件:
<many-to-one name="cus" column="cid" lazy="false" fetch="join"/>
測試:
@Test
?? publicvoid testHQL(){
?????
????? Session session = HibernateUtil.getSession();
????? List<Orders> ord = session.createQuery("from Orders").list();
?????
????? HibernateUtil.close();
?? }
轉(zhuǎn)載于:https://www.cnblogs.com/yangkai-cn/archive/2013/01/03/4016991.html
總結(jié)
以上是生活随笔為你收集整理的心得14-hibernate的优化2-抓取(fetch)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ubuntu配置上位机Blackfin开
- 下一篇: push_heap算法 (即满足max-