|
數(shù)據(jù)加載方式:
在通過JDBC操作數(shù)據(jù)實(shí),我們只能通過SQL語句來加載我們所需要的數(shù)據(jù),但是到了Hibernate世界中(確切的說,是到了對象關(guān)系映射的世界中),由于有O-R Mapping的幫助,我們擁有了更多的自由以及更多的方法,Hibernate總共有4種數(shù)據(jù)加載方式,分別是:即時(shí)加載,延遲加載,預(yù)先加載,批量加載,接下來我們分別討論這四種加載方式,以及它們的使用方法,然后在下一節(jié)我們重點(diǎn)討論延遲加載。
1、 即時(shí)加載:
即時(shí)加載是指,當(dāng)實(shí)體加載完成后,立即加載該實(shí)體所關(guān)聯(lián)的數(shù)據(jù)。我們以前面討論一對多關(guān)聯(lián)映射的例子為例:客戶和客戶訂購的貨物是一對多的關(guān)系,所以我們在配置客戶實(shí)體類的集合時(shí)采用了下面的配置:
<set name=”orders” table=”order” inverse=”true” cascade=”none” sort=”true” lazy=”false”>
<key column=”c_id”/>
<one-to-many class=”com.neusoft.entity.Order”/>
</set>
我們注意,在set元素的lazy屬性被設(shè)置為true,此時(shí)就啟動了即時(shí)加載,看下面的代碼:
String hql=”from Customer c where c.name=’zx’ ”;
List list=session.createQuery(hql).list();
System.out.println(“query finish….../n”);
Iterator it=list.iterator();
While(it.hasNext()){
Customer customer=(Customer)it.next();
Set set=customer.getOrders();
}
當(dāng)我們運(yùn)行上面的代碼時(shí),會生成如下類似的輸出:
Select * from customer where name=’zx’;
Select * from order where id=’1’;
query finish…...
我們看到當(dāng)執(zhí)行查詢Customer實(shí)體操作時(shí),會自動加載它所關(guān)聯(lián)的Order實(shí)體對象,因此會出現(xiàn)第二條查詢語句,這就是即時(shí)加載的基本原理,當(dāng)宿主實(shí)體加載時(shí),會立即自動加載關(guān)聯(lián)的實(shí)體對象,并完成關(guān)聯(lián)實(shí)體對象的屬性填充和實(shí)體對象的構(gòu)造。
2、 延遲加載:
在即時(shí)加載中,當(dāng)加載Customer對象時(shí),通過另一條查詢語句自動加載了它所關(guān)聯(lián)的實(shí)體對象,但是如果我們只需要Customer對象數(shù)據(jù),而不需要它所關(guān)聯(lián)的Order對象的數(shù)據(jù),此時(shí)就造成了性能的無謂損耗。延遲加載機(jī)制的引入,使這個(gè)問題得到了化解。還以上面的例子為例,當(dāng)我們想起用延遲加載機(jī)制時(shí),我們要進(jìn)行如下的配置:
<set name=”orders” table=”order” inverse=”true” cascade=”none” sort=”true” lazy=”true”>
<key column=”c_id”/>
<one-to-many class=”com.neusoft.entity.Order”/>
</set>
在set元素的lazy屬性設(shè)置成true,此時(shí)就啟動了延遲加載,當(dāng)我們再次運(yùn)行上面的代碼時(shí),會生成如下的輸出:
Select * from customer where name=’zx’;
query finish…...
Select * from order where id=’1’;
注意與即時(shí)加載不同,當(dāng)我們執(zhí)行查詢Customer對象時(shí),并沒有立即加載它所關(guān)聯(lián)的Order對象,只有執(zhí)行確實(shí)獲取關(guān)聯(lián)的Order對象數(shù)據(jù)時(shí),才會發(fā)起對關(guān)聯(lián)對象的查詢,這就是所謂的延遲加載機(jī)制,只有當(dāng)確實(shí)需要獲取關(guān)聯(lián)數(shù)據(jù)時(shí),才去真正加載關(guān)聯(lián)對象。有關(guān)延遲加載的高級應(yīng)用我們將在下一節(jié)中重點(diǎn)介紹。
3、 預(yù)先加載:
要啟用預(yù)先加載,必須如下配置:
<set name=”orders” table=”order” inverse=”true” cascade=”none” sort=”true” out-join=”auto”>
<key column=”c_id”/>
<one-to-many class=”com.neusoft.entity.Order”/>
</set>
如我們所見,將out-join設(shè)置為true,這時(shí)就啟用了預(yù)先加載,預(yù)先加載與即時(shí)加載不同,它是通過外連接來加載關(guān)聯(lián)實(shí)體的,而不是通過兩條查詢語句來加載關(guān)聯(lián)實(shí)體,如上配置當(dāng)我們再次執(zhí)行上面的代碼時(shí),會生成如下的輸出:
Select * from customer c left outer join order o on c.id=o.id and c.name=’zx’;
4、 批量加載:
所謂批量加載,就是通過批量提交多個(gè)限定條件,一次完成多個(gè)數(shù)據(jù)的讀取。比如我們有如下的SQL語句:
Select * from customer where id=’1’;
Select * from customer where id=’2’;
我們可以將以上兩個(gè)SQL語句合并成如下形式:
Select * from customer where id=’1’ or id=’2’;
這就是批量加載的原理,當(dāng)使用批量加載時(shí),Hibernate會自動在當(dāng)前session中查找是否還有同類型的待加載的實(shí)體對象,如果有就將查詢條件合并到當(dāng)前的查詢語句中,這樣就通過一次數(shù)據(jù)庫操作完成了多次讀取任務(wù),從而提高了讀取性能。如果想啟用批量加載,必須如下配置實(shí)體類的class元素:
<class name=”customer” table=”customer” batch-size=”5”>
通過指定batch-size屬性的值,來指定批量加載尺寸以及啟用批量加載,以上配置每次最多同時(shí)加載5個(gè)同類型實(shí)體對象。一般來說,batch-size應(yīng)該設(shè)置成一個(gè)合理的小的整數(shù)值。(一般設(shè)置成<10)
|
|
|