Hiberante有三种检索策略:立即检索,延迟检索,迫切左外连接检索.从检索策略的作用域分:类级别检索,关联级别检索.从检索使用的语句分:load(),get(),find().可以在配置文件或者以硬代码的方式指定检索策略.
类级别检索:默认检索策略是立即检索,并且在编程时推荐使用这种方式.如果使用了延迟检索策略,Hiberate会在调用程序调用getXxx()或者setXxx()这些方法之前,根据OID为持久化类生成一个代理类,这个代理类仅仅初始化了OID属性,因此可以节省内存.看以下代码:
A:tx=session.beginTransaction();
B:Customer customer=(Customer)session.load(Customer.class,new Long(1));
C:customer.getId();
D:customer.getName();
E:tx.commit();
当使用立即检索策略时,程序执行到B时,Hiberate会立即执行查询CUSTOMER表的select()语句:select* from CUSTOMER where CUSTOMER_ID=1;并在Session缓存中存放根据搜到的信息生成的所有Cusomer对象.当使用延迟检索策略时,程序执行到B时只是根据OID=1生成Customer的代理类(这个代理类除了有ID属性为1外,其他的属性都为null),执行到C时,仍然不会去检索数据库,因为这个代理类已经有ID属性了,直到执行到D时,才会去执行select* from CUSTOMER where ID=1,从而初始化代理类.由于一般地程序通过session的Load方法加载一个持久化对象后,总是会立即访问它,因此在类级别的检索时,一般推荐使用立即检索.另外,在类级别的检索时,get()和find()方法总是使用立即检索(它们会覆盖掉配置文件).
一对多关联级别:默认检索策略是立即检索.一对多关联的hbm.xml文件:
<set name="orders" inverse="true">
<key column="CUSTOMER_ID"/>
<one-to many class="Order"/>
</set>
由于在Session的缓存中存放的是相互关联的对象图,当使用默认检索策略时,程序执行到B时,Hibernate会执行以下select()语句:select* from CUSTOMER where ID=1;select* from Orders where USTOMER _ID=1;并在Session缓存中形成Customer类的对象,和若干个Order类的对象.如果应用只是想要Customer的信息,这样的结果显然浪费了内存,降低了性能.因此一对多级别的检索优先推荐使用延迟检索.当使用延迟检索策略时,程序执行到B时,只执行select* from CUSTOMER where ID=1并且只形成Customer类的对象,只有到后来程序执行到order.iterator()这样的方法时,才去执行select* from Orders where USTOMER _ID=1,并生成Order类的对象.为使用延迟检索策略,可以在<set>中这样写<set name="orders" inverse="true" lasy=true>.一对多关联级别的检索除了使用默认的立即检索和延迟检索外,还可以选用迫切左外连接检索:<set name="orders" inverse="true" outer_join="true">,当程序执行到Customer customer=(Customer)session.get(Customer.class,new Long(1));时,执行这个select()语句:select* from CUSTOMER left outer join ORDERS on CUSTERS.ID=ORDERS.SUTOMER_ID whereCUSTOMER.ID=1;可以将迫切左外连接检索看作是一个特殊的立即检索,它也是立即执行检索,但是与立即检索对数据库的操作方式上不一样.
多对一和一对一关联级别:默认检索策略是外连接检索.多对一关联的hbm.xml文件
<many-to-one name="customer"
column="CUSTOMER_ID"
class=Customer/> 对于一对一的关联,用<one-to-one>.
可以在两个地方设置检索策略的方式:<class>的lazy和<many-to-one>的outer-join中.具体分析过程与上面差不多,另外,Session的find()方法会忽略配置文件中的外连接检索的配置.下面看一个具体实例.