班级和学生是一对多关联:
班级表:
学生表:
Student.hbm.xml
<!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.xxc.domain.Student">
<id name="sid" type="long">
<column name="sid"></column>
<generator class="increment"></generator>
</id>
<property name="sname" type="string" length="20" column="sname"/>
<many-to-one name="clazz" column="cid" cascade="all"/>
</class>
</hibernate-mapping>
Class.hbm.xml
<!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.xxc.domain.Clazz">
<id name="cid" type="long">
<column name="cid" length="5"/>
<generator class="increment"/>
</id>
<property name="cname" type="string" length="20"/>
<!-- fetch抓取策略:select join subselect-->
<set name="stus" inverse="false" cascade="all" fetch="subselect">
<key column="cid"></key>
<one-to-many class="com.xxc.domain.Student"/>
</set>
</class>
</hibernate-mapping>
需求:查询出所有班级(4个班级)的所有学生信息
public void testLoad(){
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Query query = session.createQuery("from Clazz where cid in(1,2,3,4)");
List<Clazz> list_clzz = query.list();
for(Clazz clzz : list_clzz){
Set<Student> stus = clzz.getStus();
for(Student stu : stus){
//System.out.println(stu.getSname());
}
}
transaction.commit();
session.close();
}
1.如果Class.hbm.xml的set标签的fetch="select"(即默认情况)那么一共会发出4+1条sql语句
--1.这一条sql语句是查询所有班级引起的,from Clazz where cid in(1,2,3,4)这句hql引起的
Hibernate:
select
clazz0_.cid as cid0_,
clazz0_.cname as cname0_
from
Clazz clazz0_
where
clazz0_.cid in (
1 , 2 , 3 , 4
)
--2.以下4条sql语句是查询4个班级各自的学生集合引起的
Hibernate:
select
stus0_.cid as cid0_1_,
stus0_.sid as sid1_,
stus0_.sid as sid1_0_,
stus0_.sname as sname1_0_,
stus0_.cid as cid1_0_
from
Student stus0_
where
stus0_.cid=?
Hibernate:
select
stus0_.cid as cid0_1_,
stus0_.sid as sid1_,
stus0_.sid as sid1_0_,
stus0_.sname as sname1_0_,
stus0_.cid as cid1_0_
from
Student stus0_
where
stus0_.cid=?
Hibernate:
select
stus0_.cid as cid0_1_,
stus0_.sid as sid1_,
stus0_.sid as sid1_0_,
stus0_.sname as sname1_0_,
stus0_.cid as cid1_0_
from
Student stus0_
where
stus0_.cid=?
Hibernate:
select
stus0_.cid as cid0_1_,
stus0_.sid as sid1_,
stus0_.sid as sid1_0_,
stus0_.sname as sname1_0_,
stus0_.cid as cid1_0_
from
Student stus0_
where
stus0_.cid=?
2.如果Class.hbm.xml的set标签的fetch="subSelect",子查询,那么一共只发出2条sql语句
--1.这一条sql语句是查询所有班级引起的,from Clazz where cid in(1,2,3,4)这句hql引起的
Hibernate:
select
clazz0_.cid as cid0_,
clazz0_.cname as cname0_
from
Clazz clazz0_
where
clazz0_.cid in (
1 , 2 , 3 , 4
)
--2.由于配置了fetch="subselect"属性,在查询学生的时候,就按照学生的cid in(1,2,3,4)的子查询形式进行查询
Hibernate:
select
stus0_.cid as cid0_1_,
stus0_.sid as sid1_,
stus0_.sid as sid1_0_,
stus0_.sname as sname1_0_,
stus0_.cid as cid1_0_
from
Student stus0_
where
stus0_.cid in (
select
clazz0_.cid
from
Clazz clazz0_
where
clazz0_.cid in (
1 , 2 , 3 , 4
)
)
3.如果Class.hbm.xml的set标签的fetch="join"(左外连接),因为子查询可以满足要求查询出数据,所以生成的sql语句是和上面fetch="select"的一样,最差的查询效率
public void testLoad(){
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Clazz clazz = (Clazz) session.get(Clazz.class, 1L);//查询班级的时候,会使用左外连接查询学生
transaction.commit();
session.close();
}
Hibernate:
select
clazz0_.cid as cid0_1_,
clazz0_.cname as cname0_1_,
stus1_.cid as cid0_3_,
stus1_.sid as sid3_,
stus1_.sid as sid1_0_,
stus1_.sname as sname1_0_,
stus1_.cid as cid1_0_
from
Clazz clazz0_
left outer join
Student stus1_
on clazz0_.cid=stus1_.cid
where
clazz0_.cid=?
结论: