程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Hibernate延遲加載道理與完成辦法

Hibernate延遲加載道理與完成辦法

編輯:關於JAVA

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法式設計有所贊助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved