1. 类级别检索策略
1.1 立即检索
1.2 延迟检索
2. 一对多和多对多关联的检索策略
2.1 批量延迟和批量立即检索
2.1 迫切左外连接检索
3.多对一和一对多关联的检索策略。
3.1 迫切左外连接检索
3.2延迟检索
3.3立即检索
3.4批量延迟检索和批量立即检索
1 类级别的检索策略
类级别可选的检索策略包括立即检索和延迟检索,默认为立即检索,即<class>元素的lazy属性为false
立即检索
Customer.hbm.xml文件中<class name=”mypack.Customer” table=”CUSTOMER” lazy=”false”>
通过(Customer )session.load(Customer.class,new Long(1));会立即执行查询语句:
select * from CUSTOMERS wher ID=1;对于是否检索关联的Order对象要看Order的检索策略是立即检索策略,会执行查询ORDERS表的SQL语句:
select * from ORDERS wher CUSTOMER_ID=1;
延迟检索
Customer.hbm.xml文件中<class name=”mypack.Customer” table=”CUSTOMER” lazy=”true”>.当执行Session的load()方法时,Hibernate不会立即执行查询CUSTOMERS表的select语句,仅仅返回Customer类的代理类的实例,它有以下特征:
1.
<class>元素的lazy属性为true时,会影响Session的load方法,如:
1.
2.
3.
4.
2 一对多和多对多关联的检索策略
用<set>来配置一对多关联及多对多关联,如配置Customer和Order类的一对多关联:
<set name=”orders” inverse=”true” >
<key column=”CUSTOMER_ID” />
</set>
<set>元素有一个lazy和outer-join属性。它们取不同的值的检索策略如图:
lazy属性 | outer-join属性 | 检索策略 |
false | false | 立即检索,这是默认策略 |
false | true | 迫切左外连接检索 |
true | false | |
true | true | 没有任何意义(矛盾的设置) |
在Customer类中定义了一个java.util.Set集合类型的orders属性,不管有没有设置延迟检索策略,Session的检索方法在为Customer对象的orders属性赋值时,总是引用集合代理类的实例
迫切左外连接检索
<set name=”orders” outer-join=”true”>
当执行session.get(Customer.class,new Long(1));时会用表连接格式检索关联的Order对
立即检索
延迟检索
3 多对一和一对一关联的检索策略
1.
2.
3.
多对一,要看一的映射文件 (Customer的映射文件)
迫切左外连接检索
1.因为检索策略对get()方法无效(对find()也是),因此立即检索Order对象
2.因为<many-to-one>的outer-join属性为true.因此用外连接检索Customer对象
3.根据Customer的映射文件配置的策略,对Order对象检索.总的执行语句为:
select * from ORDERS left outer join CUSTOMERS on ….where ORDERS.ID=1
select * from ORDERS where CUSTOMER_ID=1
如果Customer.hbm.xml文件中<set>的outer-join属性为true,那么检索Customer而触发检索Order对象也用迫切左外连接.语句为:
select * from ORDES o1 left outer join CUSTOMERS c1 on…left outer join ORDERS o2….如果select语句的外连接表数目太多,会影响检索性能,此时可以通过Hibernate配置文件中的hibernate.max_fetch_depth属性来控制连接深度,如果设为1,语句就变成:
select * from ORDERS left outer join CUSTOMERS on ….where ORDERS.ID=1
select * from ORDERS where CUSTOMER_ID=1
延迟检索
立即检索
4 批量延迟检索和批量立即检索
List orderLists=session.find(“from Order as c”);
Iterator orderIterator=orderLists.iterator();
Order order1=(Order)orderIterator.next();
Order order2=(Order)orderIterator.next();
Order order3=(Order)orderIterator.next();
Order order4=(Order)orderIterator.next();
Customer customer1=order1.getCustomer();
if(customer1!=null)customer1.getName();
Customer customer2=order2.getCustomer();
if(customer2!=null)customer2.getName();
Customer customer3=order3.getCustomer();
if(customer3!=null)customer3.getName();
Customer customer4=order4.getCustomer();
if(customer4!=null)customer4.getName();
检索Order用find()方法,检索策略无效,因此立即检索Order对象。执行:
select * from ORDERS;
假定Customer的lazy=”true”,就延迟检索Customer,只要ORDERS的CUSTOMER_ID不为null,就创建一个Customer代理类实例给Order对象,它的OID和CUSTOMER_ID相同。当执行customer1.getName()时,才初始化OID为1的CUstomer代理类实例,执行完上向的代码要执行四条查询CUSTOMERS表的select语句(同一个OID的Customer代理实例初始一次),为了减少语句。可以设置Customer.hbm.xml文件中的<class>元素的batch-size属性:
<class name=”nypack.Customer” table=”CUSTOMERS” lazy=”true” batch-size=”3”>这样就可以一下子初始化三个不同OID的代理类实例。它执行的语句如:
select * from CUSTOMERS wher ID=1 or ID=2 or ID=3 ,如果batch-size值过大,会导致延迟加载失去意义
假如Customer.hbm.xml中的<class…batch-size=”4” lazy=”false”>,Order.hbm.xml文件中的<many-to-one outer-join=”false”>那么采用立即检索。如:
List orderLists=session.find(“from Order as c”);
会对与Order关联的Customer采用批量立即检索,对与Customer关联的Order也采用批量立即检索.总执行语句如:
select * from ORDERS;
select * from CUSTOMERS where ID=1 or ID=2 or ID=3 or ID=4;
select * from ORDERS where CUSTOMER_ID=1 or CUSTOMER_ID=2 or ………..
Hibernate对迫切左外连接检索的限制。
1.
2.
例子略
在应用程序是显式指定迫切左外连接检索策略
三种策略的优缺点
检索策略 | 优点 | 缺点 |
立即检索 | 初始化对象,可以方便访问 | select 语句数目多;可能加载不需要访问的对象,浪费内存空间 |
延迟检索 | 避免加载不需要访问的对象,提高性能,节省内存空间 | 访问对象要对代理类实例初始化 |
迫切左外连接检索 | 初始化对象,方便访问;使用外连接,减少select语句 | 可能加载不需要访问的对象,浪费内存空间;检索语句复杂,影响性能 |