Hibernate延遲加載道理與完成辦法。本站提示廣大學習愛好者:(Hibernate延遲加載道理與完成辦法)文章只能為提供參考,不一定能成為您想要的結果。以下是Hibernate延遲加載道理與完成辦法正文
本文實例講述了Hibernate延遲加載道理與完成辦法。分享給年夜家供年夜家參考,詳細以下:
為了進一步優化Hibernate的機能,可使用:
延遲加載技巧、治理數據抓取戰略、停止緩存治理 等方面斟酌來進步Hibernate的機能。
1. 延遲加載(load)
延遲加載(load)是Hibernate為進步法式履行效力而供給的一種機制,即只要真正應用該對象的數據時才會創立。
延遲加載的進程:經由過程署理(Proxy)機制來完成延遲加載。Hibernate從數據庫獲得某一個對象數據時、獲得某一個對象的聚集屬性值時,或獲得某一個對象所聯系關系的另外一個對象時,因為沒有應用該對象的數據(除標識符外),Hibernate其實不從數據庫加載真實的數據,而只是為該對象創立一個署理對象來代表這個對象,這個對象上的一切屬性都為默許值;只要在真正須要應用該對象的數據時才創立這個真實的對象,真正從數據庫中加載它的數據。
當挪用Session上的load()辦法加載一個實體時;當Session加載某個實體時,會對這個實體中的聚集屬性值采取延遲加載;當Session加載某個實體時,會對這個實體所單端聯系關系的另外一個實體對象采取延遲加載
封閉延遲加載:在加載單個實體時,可使用get()辦法。
關於實體中的聚集屬性,可以在這個聚集的(<set>,<bag>,<list>…)添加屬性lazy="false"。單端聯系關系另外一個實體對象時,可以在映照文件中設置裝備擺設<one-to-one>,<many-to-one> 添加屬性lazy="false"留意:one-to-one不克不及有constrained=true(發生的sql語句中顯示外鍵),不然懶加載不起感化。
2. Hibernate中默許采取延遲加載的情形重要有以下幾種:
• 當挪用Session上的load()辦法加載一個實體時會采取延遲加載。
• 當Session加載某個實體時,會對這個實體中的聚集屬性值采取延遲加載。(one-to-many)
• 當Session加載某個實體時,會對這個實體所單端聯系關系(one-to-one, many-to-one)的另外一個實體對象采取延遲加載。
• 第二種和第三種的差別是:第二種情形下撤消延時加載的辦法是在雙方即有set屬性的一方的映照文件的set標簽後設置懶加載的屬性lazy="false";第三種情形則是在多方即有many-to-one的一方的映照文件中的many-to-one標簽後設置lazy="false"。
可以或許懶加載的對象都是被改寫過的署理對象,當相干聯的session沒有封閉時,拜訪這些懶加載對象(署理對象)的屬性(getId和getClass除外)hibernate會初始化這些署理,或用Hibernate.initialize(proxy)來初始化署理對象;當相干聯的session封閉後,再拜訪懶加載的對象將湧現異常。
3. 抓取戰略(fetch)
經由過程設置裝備擺設"抓取戰略"來直接影響session的get()和load()辦法的查詢後果。
單端聯系關系<many-to-one><one-to_one>上的抓取戰略:
可以給單端聯系關系的映照元素添加fetch屬性。select:延遲加載; join:在統一條select語句應用內銜接來取得對象的數據和它聯系關系對象的數據,此時聯系關系對象的延遲加載掉效。
聚集屬性上的抓取戰略:
select:延遲加載;join:在統一條select語句應用內銜接來取得對方的聯系關系聚集。此時聯系關系聚集上的lazy會掉效。subselect:別的發送一條查詢語句或子查詢抓取。這個戰略對HQL的查詢也起感化。
4. 延遲加載案例剖析
情形一:單個實體挪用load()辦法撤消懶加載
package com.hbsi.test; import org.hibernate.Session; import org.junit.Test; import com.hbsi.domain.User; import com.hbsi.utils.HibernateUtil; publicclass TestLazy { //測試get()辦法;get()辦法不論你有無用到,總會履行sql語句 @Test publicvoid testGet(){ Session session = HibernateUtil.getSession(); User user = (User) session.get(User.class,1); // System.out.println(user.getName()); HibernateUtil.close(); //這裡要留意的是:即便封閉了session,使user處於托管狀況,依然可以可使用user對象;這是由於固然處於托管狀況,然則這個對象是存在屬性值的對象,並沒有把他刪除,只是隔斷了它與數據庫的打交道的通道。 System.out.println(user.getName()); } //測試load()辦法;不履行sql語句,用到的時刻才履行 @Test publicvoid testLoad(){ Session session = HibernateUtil.getSession(); User user = (User) session.load(User.class,1); //這裡輸入id也不會履行sql語句,直接從下面你傳出來的id中獲得id,沒有從數據庫中查找,所以也不履行sql語句 System.out.println(user.getId()); //而輸入name就紛歧樣了,這時候其實就是實例化了署理對象,這是的署理對象有了name的屬性,這時候即便你封閉了session,也能夠經由過程這個對象獲得到name;假如正文這句,即不實例化署理對象,又在封閉session後履行輸入name屬性,這時候會報錯:could not initialize proxy // System.out.println(user.getName()); HibernateUtil.close(); System.out.println(user.getName()); } }
情形二:set聚集上撤消懶加載
測試假如在映照文件中將聚集屬性中的懶加載設置為false後將連帶著orders表中數據一塊提出來,即兩條select語句
@Test publicvoid find(){ Session session = HibernateUtil.getSession(); Customer cus = (Customer) session.get(Customer.class,3); System.out.println(cus.getCname()); //用到上面這類辦法輸入會湧現兩天sql語句,並且是離開的;假如用到懶加載會湧現先輸入兩條sql語句,在輸入成果 //這裡不克不及直接辦法鏈式輸入cus.getOrd().getOname();由於cus.getOrd()前往的是一個set聚集 Set<Orders> orders = cus.getOrd(); System.err.println(orders.size()); HibernateUtil.close(); }
辦法三:<one-to-one>,<many-to-one> 撤消懶加載
@Test publicvoid find(){ //默許應用懶加載,即用著一條sql語句就輸入一條;假如設置延時加載為false後輸入兩條sql語句,將不須要的顧客信息也查出來 Session session = HibernateUtil.getSession(); Orders ord = (Orders) session.get(Orders.class,3); System.out.println(ord.getOname()); HibernateUtil.close(); }
願望本文所述對年夜家基於Hibernate框架的Java法式設計有所贊助。