小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Hibernate入門之延遲初始 Lazy Initialization

 WindySky 2007-07-15
延遲初始 Lazy Initialization
 首先我們來看看這個主題:
入門 11 - Set 映射
 依這個主題所完成的例子,請將Hibernate的show_sql設(shè)定為true,當(dāng)我們使用下面的程序時,觀看控制臺所使用的SQL:
HibernateTest.java
import onlyfun.caterpillar.*;
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
import java.util.*;

public class HibernateTest {
public static void main(String[] args) throws HibernateException {
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();

List users = session.find("from User");

session.close();
sessionFactory.close();
}
}
 SQL運(yùn)作的例子如下:
Hibernate: select user0_.USER_ID as USER_ID, user0_.NAME as NAME from USER user0_
Hibernate: select addrs0_.USER_ID as USER_ID__, addrs0_.ADDRESS as ADDRESS__ from ADDRS addrs0_ where addrs0_.USER_ID=?
Hibernate: select addrs0_.USER_ID as USER_ID__, addrs0_.ADDRESS as ADDRESS__ from ADDRS addrs0_ where addrs0_.USER_ID=?
 可以看到的,除了從USER表格中讀取數(shù)據(jù)之外,還向ADDRS表格讀取數(shù)據(jù),預(yù)設(shè)上,Hibernate會將所有關(guān)聯(lián)到的對象,透過一連串的SQL語句讀取并加載數(shù)據(jù),然而現(xiàn)在考慮一種情況,我們只是要取得所有USER的名稱,而不用取得它們的郵件地址,此時自動讀取相關(guān)聯(lián)的對象就是不必要的。
 在Hibernate中,集合類的映像可以延遲初始(Lazy Initialization),也就是在真正索取該對象的數(shù)據(jù)時,才向數(shù)據(jù)庫查詢,就這個例子來說,就是我們在讀取User時,先不取得其中的 addrs屬性中之對象數(shù)據(jù),由于只需要讀取User的name屬性,此時我們只要執(zhí)行一次select即可,真正需要addrs的數(shù)據(jù)時,才向數(shù)據(jù)庫要求。
 要使用Hibernate的延遲初始功能,只要在集合類映像時,加上lazy="true"即可,例如在我們的User.hbm.xml中的<set>中如下設(shè)定:
User.hbm.xml
<set name="addrs" table="ADDRS" lazy="true">
<key column="USER_ID"/>
<element type="string" column="ADDRESS" not-null="true"/>
</set>
 我們來看看下面這個程序:
HibernateTest.java
import onlyfun.caterpillar.*;
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
import java.util.*;

public class HibernateTest {
public static void main(String[] args) throws HibernateException {
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();

List users = session.find("from User");

for (ListIterator iterator = users.listIterator(); iterator.hasNext(); ) {
User user = (User) iterator.next();
System.out.println(user.getName());
Object[] addrs = user.getAddrs().toArray();

for(int i = 0; i < addrs.length; i++) {
System.out.println("\taddress " + (i+1) + ": " + addrs[i]);
}
}

session.close();
sessionFactory.close();
}
}
 在沒有使用延遲初始時,控制臺會顯示以下的內(nèi)容:
Hibernate: select user0_.USER_ID as USER_ID, user0_.NAME as NAME from USER user0_
Hibernate: select addrs0_.USER_ID as USER_ID__, addrs0_.ADDRESS as ADDRESS__ from ADDRS addrs0_ where addrs0_.USER_ID=?
Hibernate: select addrs0_.USER_ID as USER_ID__, addrs0_.ADDRESS as ADDRESS__ from ADDRS addrs0_ where addrs0_.USER_ID=?
caterpillar
address 1: caterpillar@caterpillar.onlyfun.net
address 2: justin@caterpillar.onlyfun.net
address 3: justin@fake.com
momor
address 1: momor@fake.com
address 2: momor@caterpillar.onlyfun.net
 如果使用延遲初始,則會出現(xiàn)以下的內(nèi)容:
Hibernate: select user0_.USER_ID as USER_ID, user0_.NAME as NAME from USER user0_
caterpillar
Hibernate: select addrs0_.USER_ID as USER_ID__, addrs0_.ADDRESS as ADDRESS__ from ADDRS addrs0_ where addrs0_.USER_ID=?
address 1: caterpillar@caterpillar.onlyfun.net
address 2: justin@caterpillar.onlyfun.net
address 3: justin@fake.com
momor
Hibernate: select addrs0_.USER_ID as USER_ID__, addrs0_.ADDRESS as ADDRESS__ from ADDRS addrs0_ where addrs0_.USER_ID=?
address 1: momor@fake.com
address 2: momor@caterpillar.onlyfun.net
 請注意SQL語句出現(xiàn)的位置,在使用延遲初始功能前,會將所有相關(guān)聯(lián)到的數(shù)據(jù)一次查完,而使用了延遲初始之后,只有在真正需要addrs的數(shù)據(jù)時,才會使用SQL查詢相關(guān)數(shù)據(jù)。
 Hibernate實(shí)現(xiàn)延遲初始功能的方法,是藉由實(shí)現(xiàn)一個代理對象(以Set來說,其實(shí)現(xiàn)的代理子類是 net.sf.hibernate.collection.Set),這個代理類實(shí)現(xiàn)了其所代理之對象之相關(guān)方法,每個方法的實(shí)現(xiàn)實(shí)際上是委托(delegate)真正的對象,查詢時加載的是代理對象,在真正呼叫對象的相關(guān)方法之前,不會去初始真正的對象來執(zhí)行被呼叫的方法。
 所以為了能使用延遲初始,您在使用集合映像時,在宣告時必須是集合類的接口,而不是具體的實(shí)現(xiàn)類(例如宣告時使用Set,而不是HashSet)。
 使用延遲初始的一個問題是,由于在需要時才會去查詢數(shù)據(jù)庫,所以session不能關(guān)閉,如果在session關(guān)閉后,再去要求被關(guān)聯(lián)的對象,將會發(fā)生LazyInitializationException,像是:
Set addrs = user.getAddrs();
session.close();

// 下面這句會發(fā)生LazyInitializationException
Object[] addrs = user.getAddrs().toArray();
 如果您使用了延遲初始,而在某些時候仍有需要在session關(guān)閉之后取得相關(guān)對象,則可以使用Hibernate.initialize()來先行加載相關(guān)對象,例如:
Hibernate.initialize(user.getAddrs());
session.close();
Set add = user.getAddrs();
Object[] addo = user.getAddrs().toArray();
 延遲初始只是Hibernate在取得數(shù)據(jù)時的一種策略,目的是為了調(diào)節(jié)數(shù)據(jù)庫存取時的時機(jī)以取得一些效能,除了延遲初始之外,還有其它的策略來調(diào)整數(shù)據(jù)庫存取的方法與時機(jī),這部份牽涉的討論范圍很大,有興趣的話,可以參考Hibernate in Action的4.4.5。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多