在Classes与Student一对多映射中,我们将Set里面的fetch属性设置为subselect来实现子查询。
如下示例
首先看一下set中fetch="select"即默认情况下:
生成数据类:
package com.bjsxt.hibernate; import org.hibernate.Session; public class InitData { public static void main(String[] args) { Session session = HibernateUtils.getSession(); try { session.beginTransaction(); for(int i=0; i<10; i++){ Classes classes = new Classes(); classes.setName("班级"+i); session.save(classes); for(int j=0; j<10; j++){ Student student = new Student(); student.setName("班级"+i+"的学生"+j); //在内存中建立由student指向classes的引用 student.setClasses(classes); session.save(student); } } session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); session.getTransaction().rollback(); } finally{ HibernateUtils.closeSession(session); } } }
测试类:
package com.bjsxt.hibernate; import java.io.Serializable; import java.util.Iterator; import java.util.List; import java.util.Set; import org.hibernate.Session; import junit.framework.TestCase; public class FetchTest extends TestCase { public void testFetch1() { Session session = null; try { session = HibernateUtils.getSession(); Classes classes = (Classes)session.load(Classes.class, 1); System.out.println("班级:" + classes.getName()); Set students = classes.getStudents(); for (Iterator iter = students.iterator(); iter.hasNext();) { Student student = (Student)iter.next(); System.out.println(student.getName()); } }catch(Exception e) { e.printStackTrace(); }finally { HibernateUtils.closeSession(session); } } public void testFetch2() { Session session = null; try { session = HibernateUtils.getSession(); List Classes = session.createQuery("select c from Classes c where c.id in(1, 2, 3)").list(); for (Iterator iter = Classes.iterator(); iter.hasNext();) { Classes cls = (Classes)iter.next(); System.out.println("班级:" + cls.getName()); for (Iterator iter1 = cls.getStudents().iterator(); iter1.hasNext();) { Student student = (Student)iter1.next(); System.out.println(student.getName()); } } }catch(Exception e) { e.printStackTrace(); }finally { HibernateUtils.closeSession(session); } } }
分别列出方法一与方法二的测试结果:
Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=? 班级:班级0 Hibernate: select students0_.classid as classid0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.classid as classid1_0_ from t_student students0_ where students0_.classid=? 班级0的学生8 班级0的学生1 班级0的学生7 班级0的学生5 班级0的学生3 班级0的学生4 班级0的学生0 班级0的学生6 班级0的学生9 班级0的学生2
Hibernate: select classes0_.id as id0_, classes0_.name as name0_ from t_classes classes0_ where classes0_.id in (1 , 2 , 3) 班级:班级0 Hibernate: select students0_.classid as classid0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.classid as classid1_0_ from t_student students0_ where students0_.classid=? 班级0的学生7 班级0的学生2 班级0的学生3 班级0的学生1 班级0的学生0 班级0的学生9 班级0的学生4 班级0的学生8 班级0的学生6 班级0的学生5 班级:班级1 Hibernate: select students0_.classid as classid0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.classid as classid1_0_ from t_student students0_ where students0_.classid=? 班级1的学生9 班级1的学生0 班级1的学生6 班级1的学生8 班级1的学生7 班级1的学生2 班级1的学生5 班级1的学生3 班级1的学生1 班级1的学生4 班级:班级2 Hibernate: select students0_.classid as classid0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.classid as classid1_0_ from t_student students0_ where students0_.classid=? 班级2的学生6 班级2的学生9 班级2的学生3 班级2的学生1 班级2的学生2 班级2的学生7 班级2的学生8 班级2的学生4 班级2的学生0 班级2的学生5
下面更改fetch="subselect"
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.bjsxt.hibernate.Classes" table="t_classes"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <!-- <set name="students" cascade="all" order-by="id"> --> <set name="students" inverse="true" fetch="subselect"> <key column="classid"/> <one-to-many class="com.bjsxt.hibernate.Student"/> </set> </class> </hibernate-mapping>
同样,将两个方法的测试结果列出如下:
Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=? 班级:班级0 Hibernate: select students0_.classid as classid0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.classid as classid1_0_ from t_student students0_ where students0_.classid=? 班级0的学生3 班级0的学生1 班级0的学生9 班级0的学生7 班级0的学生5 班级0的学生0 班级0的学生6 班级0的学生2 班级0的学生8 班级0的学生4
Hibernate: select classes0_.id as id0_, classes0_.name as name0_ from t_classes classes0_ where classes0_.id in (1 , 2 , 3) 班级:班级0 Hibernate: select students0_.classid as classid0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.classid as classid1_0_ from t_student students0_ where students0_.classid in (select classes0_.id from t_classes classes0_ where classes0_.id in (1 , 2 , 3)) 班级0的学生5 班级0的学生1 班级0的学生0 班级0的学生8 班级0的学生7 班级0的学生2 班级0的学生9 班级0的学生6 班级0的学生4 班级0的学生3 班级:班级1 班级1的学生5 班级1的学生1 班级1的学生0 班级1的学生7 班级1的学生4 班级1的学生9 班级1的学生8 班级1的学生3 班级1的学生6 班级1的学生2 班级:班级2 班级2的学生0 班级2的学生5 班级2的学生1 班级2的学生8 班级2的学生6 班级2的学生9 班级2的学生4 班级2的学生7 班级2的学生3 班级2的学生2
比较两次测试的结果我们发现,方法二的输出结果不同,当fetch="subselect"的时候,方法二进行了子查询
如:
Hibernate: select students0_.classid as classid0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.classid as classid1_0_ from t_student students0_ where students0_.classid in (select classes0_.id from t_classes classes0_ where classes0_.id in (1 , 2 , 3))