(十六)Hibernate中的延遲加載
一、什麽是延遲加載
為了節省Hibernate加載對象的性能節銷,在Hibernate中真正需要用到這個對象時,才會發出
SQL語句來抓取這個對象。這一個過程稱為延遲加載。
二、延遲加載的分類
A:實體對象的延遲加載
B:一對多|多對多的延遲加載
C:多對一|一對一的延遲加載
D:屬性的延遲加載
-
A:實體對象的延遲加載:使用session.get()和session.load()獲取對象的區別就是是否開啟延遲加載。
Hibernate只加載實體對象的ID,需要其他屬性,才真正的發出SQL來加載這個對象。
Load:采用延遲加載 加載到的是一個代理對象
Get:沒有采用延遲加載 加載到的是一個實體對象。
- 案例:
User user=(User)session.load(clazz, id);//直接返回的是代理對象
System.out.println(user.getId());//沒有發送sql語句到數據庫加載
user.getName();//創建真實的User實例,並發送sql語句到數據庫中
- 註意:1.不能判斷User=null;代理對象不可能為空
2.代理對象的限制:和代理關聯的session對象,如果session關閉後訪問代理則拋異常。session關閉之前訪問數據庫
-
B:一對多|多對多的延遲加載
fetch = FetchType.Lazy:表示開啟延遲加載。讀取班級時,不會發出讀取學生的SQL語句。等真正使用學生數據時,才會發出一條SQL語句讀取學生
fetch = FetchType.EAGER:取消延遲加裁。讀取班級會左關聯讀取學生。
@OneToMany(cascade = { CascadeType.REMOVE },fetch=FetchType.EAGER)
@JoinColumn(name = "classes_id")
@OrderBy(value = " studentID desc")
public List<StudentBean> getStuList() {
return stuList;
}
-
C : 多對一|一對一的延遲加裁
默認是取消延遲加載的。
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name = "group_id")
private GroupBean groupBean;
- 延遲加載帶來的問題: session關閉之後,再訪問代理對象(延遲加載獲取的是代理對象)會拋出“no session”異常。
package action; import java.util.Set; import javassist.compiler.ast.IntConst;import org.hibernate.Session; import org.hibernate.Transaction; import bean.ClassBean; import bean.StudentBean; import util.HibernateSessionUtil; public class Test { public static void main(String[] args) { ClassBean cla=Test.load(); //當Test.load()執行完畢之後,session就被關閉,這時候再訪問代理對象則會拋出異常。 使用session。get就不會出現這個問題 System.out.println(cla.getClassName()); } private static ClassBean load() { ClassBean cla = null; Session session = null; Transaction tran = null; try { session = HibernateSessionUtil.getSession(); tran = session.beginTransaction(); cla = (ClassBean) session.load(ClassBean.class, new Integer(2)); //使用延遲加載,獲得的是代理對象 tran.commit(); return cla; } catch (Exception e) { e.printStackTrace(); tran.rollback(); } finally { HibernateSessionUtil.closeSession(); //關閉session } return null; } }
- 橙色字體處代碼會出現“no session”異常。
(十六)Hibernate中的延遲加載