xing00 2010-05-10
Hibernate的检索策略包括类级别检索和关联级别的检索。
类级别检索策略包括立即检索和延迟检索:
立即检索:
立即加载检索方法指定的对象。如果程序加载一个持久化对象的目的是为了访问它的属性,可以采用立即检索策略。将<class中的lazy设置为false。在默认情况下,load()方法是采用延迟检索策略加载持久化对象的,而get()方法是采用立即检索策略的。
延迟检索策略:
类级别的默认检索策略。当需要加载一个持久化对象时,系统不会立即加载对象属性实例,而是仅初始化它的OID属性,这种策略占用的内存很少。
例如:
select*fromCUSTOMERSwhereID=1;
当采用load()方法时(默认检索策略为延迟检索),Hibernate不会执行CUSTOMERS表的Select语句,仅返回Customers类的代理类的实例,这个代理类包含了Customers类的所有属性,但仅初始化OID属性,其他属性都为null,只有当我们调用getXXX()的时候,才会初始化代理类中其他属性实例。
关联级别检索策略包括立即检索策略、延迟检索策略和迫切左外连接检索
在映射文件中用<set元素配置一对多关联或多对多关联关系。<set元素里面有两个属性lazy和fetch属性。下面简单介绍lazy和fetch属性:
本例采用Customer和Order两个类关联,即一个Customer对应多个Order。
lazy:主要决定orders集合被初始化的时机,即是在加载Customer对象时候就初始化就初始化,还是在程序访问orders对象的时候才初始化。当lazy为false采用前者,当lazy为true时采用后者。
fetch:取值为select或subselect时,决定初始化orders集合时的查询语句的形式,如果取值为join,决定orders集合被初始化的时机。
立即检索:lazy为false
例如:
Customercustomer=(Customer)session.get(Customer.class,newLong(1));
Setorders=customer.getOrders();
IteratororderIte=orders.iterator();
当执行get方法的时候,采用立即检索策略,Hibernate执行了一下语句:
select*fromCUSTOMERSwhereID=1;
select*fromORDERSwhereCUSTOMER_ID=1;
通过以上Select语句,Hibernate加载了一个Customer对象和与之关联的Order对象。
延迟检索策略:lazy为true
这是默认的并且应该优先考虑的检索策略。
<setname="orders"inverse="true"lazy="true"></set>
此时再运行session.get(Customer.class,newLong(1));时,仅加载Customer对象,Customer的orders属性引用一个没有初始化的集合代理类实例。
Setorders=customer.getOrders();
Iteratorit=orders.iterator();//此时orders集合代理类被初始化
迫切左外连接检索:fetch为join,lazy的值将被忽略
<setname="orders"inverse="true"fetch="join"></set>
当执行一下语句时:
Customercustomer=(Customer)session.get(Customer.class,newLong(1));
Hibernate会执行以下select语句:
select*fromCUSTOMERSleftouterjoinORDERSonCUSTOMER.ID=ORDERS.CUSTOMER_IDwhereCUSTOMERS.ID=1;
由select语句可知,该检索策略采用了SQL外连接的查询功能,优点在于减少了select语句的数目,同时又可以获取关联对象。缺点就是SQL语句的复杂度提高了,同时系统构建表连接也需要耗时操作。