抓取策略指多表关联查询的时候,Hibernate会发出多条sql进行查询,但如果设置了抓取策略,将多条SQL变成一条SQL执行,实际上就是使用join等关联查询。
如在一对多即示例Classes与Student的关联查询中:
代码:
public void testLoad(){
Session session = null;
try {
session = HibernateUtil.getSession();
session.beginTransaction();
//从classes得到student
Classes cls = (Classes)session.load(Classes.class, 1);
System.out.println(cls.getName());
Set set = cls.getStudents();
for (Iterator iterator = set.iterator(); iterator.hasNext();) {
Student object = (Student) iterator.next();
System.out.println(object.getName());
}
HibernateUtil.commit(session);
} catch (Exception e) {
HibernateUtil.roolback(session);
}finally{
HibernateUtil.close(session);
}
}
可以看到上面要打印出classes.name和classes.student.name那么默认情况下输出的SQL是:
Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=?
classes1
Hibernate: select students0_.class_id as class3_0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from t_student students0_ where students0_.class_id=?
stu4
stu2
stu1
stu0
stu3
而我们可以使用抓取策略:
更改Classes.hbm.xml.在set中增加fetch属性
<hibernate-mapping package="com.lwf.hibernate.pojo">
<class name="Classes" table="t_classes">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="students" fetch="join">
<key column="class_id"/>
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>
更改完后再测试上面的代码,只发出一条sql,结果为:
Hibernate: select classes0_.id as id0_1_, classes0_.name as name0_1_, students1_.class_id as class3_0_3_, students1_.id as id3_, students1_.id as id1_0_, students1_.name as name1_0_, students1_.class_id as class3_1_0_ from t_classes classes0_ left outer join t_student students1_ on classes0_.id=students1_.class_id where classes0_.id=?
classes1
stu2
stu4
stu1
stu3
stu0
显然上面比较使用抓取策略后执行的SQL语句少了,性能也跟着提高了。。
上面我们是从Classes端得到Student所以在Classes.hbm.xml中的set里面加了fetch属性。
那么如果我们从Student端得到Classes要使用fetch怎么做呢?
测试方法:
public void testLoad1(){
Session session = null;
try {
session = HibernateUtil.getSession();
session.beginTransaction();
Student s = (Student)session.load(Student.class, 1);
System.out.println(s.getName());
System.out.println(s.getClasses().getName());
HibernateUtil.commit(session);
} catch (Exception e) {
HibernateUtil.roolback(session);
}finally{
HibernateUtil.close(session);
}
}
默认情况下执行:发出两条SQL
Hibernate: select student0_.id as id1_0_, student0_.name as name1_0_, student0_.class_id as class3_1_0_ from t_student student0_ where student0_.id=?
stu0
Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=?
classes1
而要执行抓取策略,更改Student.hbm.xml的many-to-one
<?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 package="com.lwf.hibernate.pojo">
<class name="Student" table="t_student">
<!-- <cache usage="read-only"/> -->
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="classes" column="class_id" fetch="join"></many-to-one>
</class>
</hibernate-mapping>
上面我们增加了fetch="join"属性
结果:
Hibernate: select student0_.id as id1_1_, student0_.name as name1_1_, student0_.class_id as class3_1_1_, classes1_.id as id0_0_, classes1_.name as name0_0_ from t_student student0_ left outer join t_classes classes1_ on student0_.class_id=classes1_.id where student0_.id=?
stu0
classes1
现在只执行一条SQL了。。。
需要提示的是其实默认情况下fetch="select"