抓取策略(fetching strategy) 是指:当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候, Hibernate如何获取关联对象的策略。抓取策略可以在O/R映射的元数据中声明,也可以在特定的HQL 或条件查询(Criteria Query)中重载声明。
Hibernate定义几种抓取策略:
u 连接抓取(Join fetching):
Hibernate通过 在SELECT语句使用OUTER JOIN(外连接)来 获得对象的关联实例或者关联集合。
u 查询抓取(Select fetching):
另外发送一条 SELECT 语句抓取当前对象的关联实体或集合。除非你显式的指定lazy="false"禁止 延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。
u 子查询抓取(Subselect fetching):
另外发送一条SELECT 语句抓取在前面查询到(或者抓取到)的所有实体对象的关联集合。除非你显式的指定lazy="false" 禁止延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。
u 批量抓取(Batch fetching)
对查询抓取的优化方案, 通过指定一个主键或外键列表,Hibernate使用单条SELECT语句获取一批对象实例或集合。
1.1. 连接抓取
fetch="join",hibernate会通过select语句使用外连接来加载其关联实体或集合。例如:
<many-to-one name="classes" column="classesid" fetch="join"/>
例子代码如下:
Classes.java public class Classes { private int id; private String name; private Set students; Student.java public class Student { private int id; private String name; private Classes classes; Student.hbm.xml <hibernate-mapping> <class name="hibernate.Student" table="t_student"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <many-to-one name="classes" column="classesid" fetch="join"/> </class> </hibernate-mapping> Classes.hbm.xml <hibernate-mapping package="hibernate"> <class name="Classes" table="t_classes"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <set name="students" inverse="true" cascade="all" fetch="join"> <key column="classesid"/> <one-to-many class="Student"/> </set> </class> </hibernate-mapping> 测试代码: public class FechTest extends TestCase {
public void testFetch1() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction();
Student student = (Student)session.load(Student.class, 1); //发出一条sql //使用left outer join连接既查询学生也查询出这个学生的班级 System.out.println("student.name=" + student.getName()); System.out.println("classes.name=" + student.getClasses().getName()); session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } } public void testFetch2() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); Classes classes = (Classes)session.load(Classes.class, 1); //发出一条sql //使用left outer join连接既查询班级也查询出这个班级下学生 System.out.println("classes.name=" + classes.getName()); for (Iterator iter=classes.getStudents().iterator(); iter.hasNext();) { Student student = (Student)iter.next(); System.out.println("student.name=" + student.getName()); } session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } } } |