關聯映射文件中<class>標簽中的lazy(懶加載)屬性
Lazy(懶加載):只有在正真使用該對象時,才會創建這個對象
Hibernate中的lazy(懶加載):只有我們在正真使用時,它才會發出SQL語句,給我們去查詢,如果不使用對象則不會發SQL語句進行查詢。
Hibernate中lazy(懶加載)的實現:
采用了第三方組件的庫,這個庫叫cglib.jar(比較流行),這個庫對我們的類生成代理類(JDK的動態代理,只能對JDK中實現了接口的類進行代理),代理可以控制源對象並且可以對源對象的功能進行增強,而cglib.jar可以對類進行代理(cglib對我們的類進行繼承,生成一個子類,這個子類作為代理類返回給你)。
只有你正真代理類的方法,則會查看你有沒有加載目標對象,如果沒有則會加載目標對象。
Lazy(懶加載)在hibernate何處使用:
1、<class>標簽上,可以取值:true/false,(默認值為:true)
2、<property>標簽上,可以取值:true/false,需要類增強工具
3、<set>、<list>集合上,可以取值:true/false/extra,(默認值為:true)
4、<one-to-one>、<many-to-one>單端關聯上,可以取值:false/proxy/noproxy
Session.load()方法支持lazy,而session.get()不支持lazy;
Hibernate的lazy生效期:
生效期和session一樣的,session關閉,lazy失效
hibernate支持lazy策略只有在session打開狀態下有效。
<class>標簽上,可以取值:true/false,(默認值為:true):
實例一:設置<class標簽上的lazy=true(默認)
@Test public void LazyTest() { session = HibernateUtil.getSession(); tx = session.beginTransaction(); // 執行此語並不會發SQL語句,只是返回一個代理類 Group group = (Group) session.load(Group.class, 1); // 不會發SQL語句,使用上面輸入的1值 System.out.println("group.id=" + group.getId()); // 此處使用對象,會發出SQL語句 System.out.println("group.name=" + group.getName()); // 提交事務 tx.commit(); }
輸出:
group.id=1
Hibernate: select group0_.id as id1_1_0_, group0_.name as name2_1_0_ from t_group group0_ where group0_.id=?
設置<class標簽上的lazy=true(默認)
@Test public void LazyTest1(){ Session session = null; Transaction tx = null; Group group = null; try { session = HibernateUtil.getSession(); tx = session.beginTransaction(); group =(Group)session.load(Group.class, 1); System.out.println("group.name=" + group.getName()); //提交事務 tx.commit(); } catch (Exception e) { e.printStackTrace(); tx.rollback(); } finally { HibernateUtil.closeSession(session); } //不能正確輸出,拋出了LazyInitalizationException異常,因為session已經關閉 //hibernate支持lazy策略只有在session打開狀態下有效。 System.out.println("group.name=" + group.getName()); }
關聯映射文件中集合標簽中的lazy(懶加載)屬性
<set>、<list>集合上,可以取值:true/false/extra,(默認值為:true)
實例一:(集合上的lazy=true(默認))
@Test public void LazyTest2() { session = HibernateUtil.getSession(); tx = session.beginTransaction(); // 不會發出SQL語句 Classes classes = (Classes) session.load(Classes.class, 1); // 發出SQL語句,因為在使用對象 System.out.println("classes.name=" + classes.getName()); // 不會發SQL語句,只會返回一個代理類,因為沒有使用對象 Set<Student> students = classes.getStudents(); // 會發出SQL語句,因為使用了對象 for (Iterator<Student> iter = students.iterator(); iter.hasNext();) { Student student = iter.next(); System.out.println(student.getName()); } // 提交事務 tx.commit(); }
實例二:集合上的lazy=true(默認)
session = HibernateUtils.getSession(); tx = session.beginTransaction(); //不會發出SQL語句 Classes classes = (Classes)session.load(Classes.class, 1); //發出SQL語句,因為在使用對象 System.out.println("classes.name=" + classes.getName()); //不會發SQL語句,只會返回一個代理類,因為沒有使用對象 Set<Student> students = classes.getStudents(); //會發出SQL語句,發出查詢全部數據的SQL,效率不高 System.out.println("student.count=" + students.size()); //提交事務 tx.commit();
實例三:集合上的lazy=false,其它保持默認
//不會發出SQL語句,因為只設置了集合上的lazy為false,其它保持默認 Classes classes = (Classes)session.load(Classes.class, 1); //發出兩條SQL語句,分別加載classes和student //並且把集合中的數據也加載上來(雖然並沒有使用集合中的對象),因為設置了集合的lazy=false System.out.println("classes.name=" + classes.getName()); //不會發SQL語句,因為已經在前面加載了數據 Set<Student> students = classes.getStudents(); //會發出SQL語句,因為已經在前面加載了數據 for (Iterator<Student> iter = students.iterator();iter.hasNext();){ Student student = iter.next(); System.out.println(student.getName()); }
實例四:集合上的lazy=false,其它保持默認
//不會發出SQL語句 Classes classes = (Classes)session.load(Classes.class, 1); //發出兩條SQL語句,分別加載classes和student //並且把集合中的數據也加載上來(雖然並沒有使用集合中的對象),因為設置了集合的lazy=false System.out.println("classes.name=" + classes.getName()); //不會發SQL語句,因為已經在前面加載了數據 Set<Student> students = classes.getStudents(); //不會發SQL語句,因為已經在前面加載了數據 System.out.println("student.count=" + students.size());
實例五:設置集合上lazy=extra,其它默認
session = HibernateUtils.getSession(); tx = session.beginTransaction(); //不會發出SQL語句 Classes classes = (Classes)session.load(Classes.class, 1); //會發出SQL語句 System.out.println("classes.name=" + classes.getName()); //不會發出SQL語句,只返回代理類 Set<Student> students = classes.getStudents(); //會發出SQL語句 for (Iterator<Student> iter = students.iterator();iter.hasNext();){ Student student = iter.next(); System.out.println(student.getName()); }
實例六:設置集合上lazy=extra,其它默認
session = HibernateUtils.getSession(); tx = session.beginTransaction(); //不會發出SQL語句 Classes classes = (Classes)session.load(Classes.class, 1); //發出兩條SQL語句 System.out.println("classes.name=" + classes.getName()); //不會發出SQL語句 Set<Student> students = classes.getStudents(); //發出SQL語句,發出一條比較智能的SQL語句(select count(id) form t_student where classesid=?) System.out.println("student.count=" + students.size()); //提交事務 tx.commit();
<one-to-one>、<many-to-one>單端關聯上的lazy(懶加載)屬性
Ø <one-to-one>、<many-to-one>單端關聯上,可以取值:false/proxy/noproxy(false/代理/不代理)
實例一:所有lazy屬性默認(支持懶加載)
session = HibernateUtils.getSession(); tx = session.beginTransaction(); //不發出SQL語句,支持lazy(懶加載) User user = (User) session.load(User.class, 3); //發出SQL語句,只加載普通屬性,集合中的數據不會加載 System.out.println("user.name=" + user.getName()); //不會發出SQL語句,只返回代理類 Group group = user.getGroup(); //發出SQL語句,因為現在真正使用對象 System.out.println("group.name=" + group.getName()); tx.commit();
實例二:將<many-to-one>中的lazy設置為false,其它默認
session = HibernateUtils.getSession(); tx = session.beginTransaction(); //不會發出SQL User user = (User) session.load(User.class, 3); //會發出SQL,發出兩條SQL,分別是User和組 //因為<many-to-one>中的lazy=false,則會加載Group System.out.println("user.name=" + user.getName()); //不會發出,已經在上面加載了數據 Group group = user.getGroup(); //不會發出,已經在上面加載了數據 System.out.println("group.name=" + group.getName()); tx.commit();
實例三:將<class>中的lazy設置為false,其它默認
session = HibernateUtils.getSession(); tx = session.beginTransaction(); //會發出SQL,因為<class>中的lazy=false User user = (User) session.load(User.class, 3); //不會發出SQL,已經在上面加載了 System.out.println("user.name=" + user.getName()); //不會發出,因為<class>標簽上的lazy只對普通屬性的影響 //<class>標簽上的lazy不會影響到單端關聯上的lazy特性 Group group = user.getGroup(); //會發出,因為開始使用對象 System.out.println("group.name=" + group.getName()); tx.commit();
