精通Hibernate——Hibernate的检索策略

在Session的缓存中存放的是互相关联的对象图。在默认情况下,当Hibernate从数据库中加载Customer对象时,会同时加载所有关联的Order对象,下面我们以Order和Customer为例介绍如何配置Hibernate的检索策略,以优化检索性能。
Session有三种检索方法:load,get和find,他们都用来从数据中检索对象。load和get按照参数指定的OID加载一个持久化对象,find按照参数指定的HQL语句加载一个或多个持久化对象,如下:

Customer customer = (Customer)session.load(Customer.class,new Long(1));
Customer customer = (Customer)session.get(Customer.class,new Long(1));
List customerList = session.find("from Customer as c where c.id = 1");

当Hibernate执行以上方法时,需要获得以下信息
1.类级别检索策略:Session的load、get或find方法直接指定检索的是Customer对象,对Customer对象到底采用立即检索还是延迟检索。
2.关联检索策略:对与Customer关联的Order对象,即Customer对象orders集合,到底采用立即检索还是延迟检索或者迫切左外连接检索,详细介绍如下:
这里写图片描述
三种检索策略的运行机制
这里写图片描述
下面详细介绍各种检索方式
1、类级别的检索策略
立即检索
类级别默认为立即检索,如下两种配置都为立即检索策略:

<class name="com.Customer" table="CUSTOMER" />
<class name="com.Customer" table="CUSTOMER" lazy="false" />

当通过session的load方法检索Customer对象时:

Customer customer = (Customer)session.load(Customer.class,new Long(1));

Hibernate会立即查询Customer表

select * from CUSTOMER where id = 1select * from ORDERS where customer_id = 1;

延迟检索
修改以上配置如下:

<class name="com.Customer" table="CUSTOMER" lazy="true" />

当执行session的load方法时,Hibernate不会立即查询CUSTOMER表的select语句,仅仅返回Customer类的代理类的实例,这个代理类具有以下特征:
1.由Hibernate在运行时动态生成,他扩展了Customer类,因此他继承了Customer类的所有属性和方法,但它的实现对于应用程序是透明的。
2.当Hibernate创建Customer代理类实例时,仅仅初始化了它的OID属性,其他属性都为null,因此这个代理类占用内存很少
3.当应用程序第一次访问Customer代理类实例时,Hibernate会初始化代理类实例,在初始化过程中执行select语句,真正从数据库加载Customer对象所有数据。但有个例外,那就是当应用程序访问Customer代理类的getId()方法时,Hibernate不会初始化代理类实例,因为在创建代理类实例的时候OID就有已经存在了,不必去数据库中查询。
2、一对多和多对多关联的检索策略
在映射文件中,用set元素来配置一对多关联多对多关联关系。Customer.hbm.xml,如下:

<set name="orders" inverse="true" >
    <key column="customer_id" />
    <one-to-many class="com.Order" />
</set>

set元素有个lazy和outer-join属性,下面具体说明:
这里写图片描述
批量延迟检索和批量立即检索
set元素有一个batch-size属性,用于为延迟检索或者立即检索策略设定批量检索的数量。批量检索能减少select语句的数目,提高检索的性能。
session的find方法用于检索所有的Customer对象,在set元素的lazy属性有true和false来控制延迟加载还是立即加载。
3、迫切左外连接检索
如果把set元素的outer-join属性设置为true

<set name="orders" inverse="true" outer-join="true" />

当检索Customer对象时,采用迫切左外连接策略来检索所有关联的Order对象,对于以下程序:

customer = (Customer)session.get(Customer.class,new Long(1));

当运行session.get()方法时,执行以下以下sql:

select * from customers left outer join orders on customer_id = orders.customer_id where customer_id = 1;

需要注意的是session的find方法会忽略映射文件中配置的迫切左外连接检索策略,即使以上set的outer-join配置为true,对于以下代码:

List customerList = session.find("from Customer as c");

仍然采用立即检索策略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值