<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 63  文章 - 0  trackbacks - 0
    <2009年4月>
    2930311234
    567891011
    12131415161718
    19202122232425
    262728293012
    3456789

    常用鏈接

    留言簿(2)

    隨筆分類

    隨筆檔案

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    延遲加載:
      延遲加載機(jī)制是為了避免一些無謂的性能開銷而提出來的,所謂延遲加載就是當(dāng)在真正需要數(shù)據(jù)的時候,才真正執(zhí)行數(shù)據(jù)加載操作。在Hibernate中提供了對實(shí)體對象的延遲加載以及對集合的延遲加載,另外在Hibernate3中還提供了對屬性的延遲加載。下面我們就分別介紹這些種類的延遲加載的細(xì)節(jié)。
    A、實(shí)體對象的延遲加載:
    如果想對實(shí)體對象使用延遲加載,必須要在實(shí)體的映射配置文件中進(jìn)行相應(yīng)的配置,如下所示:
    <hibernate-mapping>
    <class name=”com.neusoft.entity.User” table=”user” lazy=”true”>
       ……
    </class>
    </hibernate-mapping>
    通過將class的lazy屬性設(shè)置為true,來開啟實(shí)體的延遲加載特性。如果我們運(yùn)行下面的代碼:
    User user=(User)session.load(User.class,”1”);(1)
    System.out.println(user.getName());(2)
    當(dāng)運(yùn)行到(1)處時,Hibernate并沒有發(fā)起對數(shù)據(jù)的查詢,如果我們此時通過一些調(diào)試工具(比如JBuilder2005的Debug工具),觀察此時user對象的內(nèi)存快照,我們會驚奇的發(fā)現(xiàn),此時返回的可能是User$EnhancerByCGLIB$$bede8986類型的對象,而且其屬性為null,這是怎么回事?還記得前面我曾講過session.load()方法,會返回實(shí)體對象的代理類對象,這里所返回的對象類型就是User對象的代理類對象。在Hibernate中通過使用CGLIB,來實(shí)現(xiàn)動態(tài)構(gòu)造一個目標(biāo)對象的代理類對象,并且在代理類對象中包含目標(biāo)對象的所有屬性和方法,而且所有屬性均被賦值為null。通過調(diào)試器顯示的內(nèi)存快照,我們可以看出此時真正的User對象,是包含在代理對象的CGLIB$CALBACK_0.target屬性中,當(dāng)代碼運(yùn)行到(2)處時,此時調(diào)用user.getName()方法,這時通過CGLIB賦予的回調(diào)機(jī)制,實(shí)際上調(diào)用CGLIB$CALBACK_0.getName()方法,當(dāng)調(diào)用該方法時,Hibernate會首先檢查CGLIB$CALBACK_0.target屬性是否為null,如果不為空,則調(diào)用目標(biāo)對象的getName方法,如果為空,則會發(fā)起數(shù)據(jù)庫查詢,生成類似這樣的SQL語句:select * from user where id=’1’;來查詢數(shù)據(jù),并構(gòu)造目標(biāo)對象,并且將它賦值到CGLIB$CALBACK_0.target屬性中。
       這樣,通過一個中間代理對象,Hibernate實(shí)現(xiàn)了實(shí)體的延遲加載,只有當(dāng)用戶真正發(fā)起獲得實(shí)體對象屬性的動作時,才真正會發(fā)起數(shù)據(jù)庫查詢操作。所以實(shí)體的延遲加載是用通過中間代理類完成的,所以只有session.load()方法才會利用實(shí)體延遲加載,因?yàn)橹挥衧ession.load()方法才會返回實(shí)體類的代理類對象。
    B、        集合類型的延遲加載:
    在Hibernate的延遲加載機(jī)制中,針對集合類型的應(yīng)用,意義是最為重大的,因?yàn)檫@有可能使性能得到大幅度的提高,為此Hibernate進(jìn)行了大量的努力,其中包括對JDK Collection的獨(dú)立實(shí)現(xiàn),我們在一對多關(guān)聯(lián)中,定義的用來容納關(guān)聯(lián)對象的Set集合,并不是java.util.Set類型或其子類型,而是net.sf.hibernate.collection.Set類型,通過使用自定義集合類的實(shí)現(xiàn),Hibernate實(shí)現(xiàn)了集合類型的延遲加載。為了對集合類型使用延遲加載,我們必須如下配置我們的實(shí)體類的關(guān)于關(guān)聯(lián)的部分:
    <hibernate-mapping>
       <class name=”com.neusoft.entity.User” table=”user”>
    …..
    <set name=”addresses” table=”address” lazy=”true” inverse=”true”>
    <key column=”user_id”/>
    <one-to-many class=”com.neusoft.entity.Arrderss”/>
    </set>
       </class>
    </hibernate-mapping>
    通過將<set>元素的lazy屬性設(shè)置為true來開啟集合類型的延遲加載特性。我們看下面的代碼:
    User user=(User)session.load(User.class,”1”);
    Collection addset=user.getAddresses();      (1)
    Iterator it=addset.iterator();               (2)
    while(it.hasNext()){
    Address address=(Address)it.next();
    System.out.println(address.getAddress());
    }
    當(dāng)程序執(zhí)行到(1)處時,這時并不會發(fā)起對關(guān)聯(lián)數(shù)據(jù)的查詢來加載關(guān)聯(lián)數(shù)據(jù),只有運(yùn)行到(2)處時,真正的數(shù)據(jù)讀取操作才會開始,這時Hibernate會根據(jù)緩存中符合條件的數(shù)據(jù)索引,來查找符合條件的實(shí)體對象。
    這里我們引入了一個全新的概念——數(shù)據(jù)索引,下面我們首先將接一下什么是數(shù)據(jù)索引。在Hibernate中對集合類型進(jìn)行緩存時,是分兩部分進(jìn)行緩存的,首先緩存集合中所有實(shí)體的id列表,然后緩存實(shí)體對象,這些實(shí)體對象的id列表,就是所謂的數(shù)據(jù)索引。當(dāng)查找數(shù)據(jù)索引時,如果沒有找到對應(yīng)的數(shù)據(jù)索引,這時就會一條select SQL的執(zhí)行,獲得符合條件的數(shù)據(jù),并構(gòu)造實(shí)體對象集合和數(shù)據(jù)索引,然后返回實(shí)體對象的集合,并且將實(shí)體對象和數(shù)據(jù)索引納入Hibernate的緩存之中。另一方面,如果找到對應(yīng)的數(shù)據(jù)索引,則從數(shù)據(jù)索引中取出id列表,然后根據(jù)id在緩存中查找對應(yīng)的實(shí)體,如果找到就從緩存中返回,如果沒有找到,在發(fā)起select SQL查詢。在這里我們看出了另外一個問題,這個問題可能會對性能產(chǎn)生影響,這就是集合類型的緩存策略。如果我們?nèi)缦屡渲眉项愋停?
    <hibernate-mapping>
       <class name=”com.neusoft.entity.User” table=”user”>
    …..
    <set name=”addresses” table=”address” lazy=”true” inverse=”true”>
    <cache usage=”read-only”/><key column=”user_id”/>
    <one-to-many class=”com.neusoft.entity.Arrderss”/>
    </set>
       </class>
    </hibernate-mapping>
    這里我們應(yīng)用了<cache usage=”read-only”/>配置,如果采用這種策略來配置集合類型,Hibernate將只會對數(shù)據(jù)索引進(jìn)行緩存,而不會對集合中的實(shí)體對象進(jìn)行緩存。如上配置我們運(yùn)行下面的代碼:
    User user=(User)session.load(User.class,”1”);
    Collection addset=user.getAddresses();     
    Iterator it=addset.iterator();              
    while(it.hasNext()){
    Address address=(Address)it.next();
    System.out.println(address.getAddress());
    }
    System.out.println(“Second query……”);
    User user2=(User)session.load(User.class,”1”);
    Collection it2=user2.getAddresses();
    while(it2.hasNext()){
    Address address2=(Address)it2.next();
    System.out.println(address2.getAddress());
    }
    運(yùn)行這段代碼,會得到類似下面的輸出:
    Select * from user where id=’1’;
    Select * from address where user_id=’1’;
    Tianjin
    Dalian
    Second query……
    Select * from address where id=’1’;
    Select * from address where id=’2’;
    Tianjin
    Dalian
    我們看到,當(dāng)?shù)诙螆?zhí)行查詢時,執(zhí)行了兩條對address表的查詢操作,為什么會這樣?這是因?yàn)楫?dāng)?shù)谝淮渭虞d實(shí)體后,根據(jù)集合類型緩存策略的配置,只對集合數(shù)據(jù)索引進(jìn)行了緩存,而并沒有對集合中的實(shí)體對象進(jìn)行緩存,所以在第二次再次加載實(shí)體時,Hibernate找到了對應(yīng)實(shí)體的數(shù)據(jù)索引,但是根據(jù)數(shù)據(jù)索引,卻無法在緩存中找到對應(yīng)的實(shí)體,所以Hibernate根據(jù)找到的數(shù)據(jù)索引發(fā)起了兩條select SQL的查詢操作,這里造成了對性能的浪費(fèi),怎樣才能避免這種情況呢?我們必須對集合類型中的實(shí)體也指定緩存策略,所以我們要如下對集合類型進(jìn)行配置:
    <hibernate-mapping>
       <class name=”com.neusoft.entity.User” table=”user”>
    …..
    <set name=”addresses” table=”address” lazy=”true” inverse=”true”>
    <cache usage=”read-write”/><key column=”user_id”/>
    <one-to-many class=”com.neusoft.entity.Arrderss”/>
    </set>
       </class>
    </hibernate-mapping>
    此時Hibernate會對集合類型中的實(shí)體也進(jìn)行緩存,如果根據(jù)這個配置再次運(yùn)行上面的代碼,將會得到類似如下的輸出:
    Select * from user where id=’1’;
    Select * from address where user_id=’1’;
    Tianjin
    Dalian
    Second query……
    Tianjin
    Dalian
    這時將不會再有根據(jù)數(shù)據(jù)索引進(jìn)行查詢的SQL語句,因?yàn)榇藭r可以直接從緩存中獲得集合類型中存放的實(shí)體對象。
    C、       屬性延遲加載:
      在Hibernate3中,引入了一種新的特性——屬性的延遲加載,這個機(jī)制又為獲取高性能查詢提供了有力的工具。在前面我們講大數(shù)據(jù)對象讀取時,在User對象中有一個resume字段,該字段是一個java.sql.Clob類型,包含了用戶的簡歷信息,當(dāng)我們加載該對象時,我們不得不每一次都要加載這個字段,而不論我們是否真的需要它,而且這種大數(shù)據(jù)對象的讀取本身會帶來很大的性能開銷。在Hibernate2中,我們只有通過我們前面講過的面性能的粒度細(xì)分,來分解User類,來解決這個問題(請參照那一節(jié)的論述),但是在Hibernate3中,我們可以通過屬性延遲加載機(jī)制,來使我們獲得只有當(dāng)我們真正需要操作這個字段時,才去讀取這個字段數(shù)據(jù)的能力,為此我們必須如下配置我們的實(shí)體類:
    <hibernate-mapping>
    <class name=”com.neusoft.entity.User” table=”user”>
    ……
    <property name=”resume” type=”java.sql.Clob” column=”resume” lazy=”true”/>   </class>
    </hibernate-mapping>
    通過對<property>元素的lazy屬性設(shè)置true來開啟屬性的延遲加載,在Hibernate3中為了實(shí)現(xiàn)屬性的延遲加載,使用了類增強(qiáng)器來對實(shí)體類的Class文件進(jìn)行強(qiáng)化處理,通過增強(qiáng)器的增強(qiáng),將CGLIB的回調(diào)機(jī)制邏輯,加入實(shí)體類,這里我們可以看出屬性的延遲加載,還是通過CGLIB來實(shí)現(xiàn)的。CGLIB是Apache的一個開源工程,這個類庫可以操縱java類的字節(jié)碼,根據(jù)字節(jié)碼來動態(tài)構(gòu)造符合要求的類對象。根據(jù)上面的配置我們運(yùn)行下面的代碼:
    String sql=”from User user where user.name=’zx’ ”;
    Query query=session.createQuery(sql);   (1)
    List list=query.list();
    for(int i=0;i<list.size();i++){
    User user=(User)list.get(i);
    System.out.println(user.getName());
    System.out.println(user.getResume());   (2)
    }
    當(dāng)執(zhí)行到(1)處時,會生成類似如下的SQL語句:
    Select id,age,name from user where name=’zx’;
    這時Hibernate會檢索User實(shí)體中所有非延遲加載屬性對應(yīng)的字段數(shù)據(jù),當(dāng)執(zhí)行到(2)處時,會生成類似如下的SQL語句:
    Select resume from user where id=’1’;
    這時會發(fā)起對resume字段數(shù)據(jù)真正的讀取操作。
    posted on 2009-04-11 10:35 lanxin1020 閱讀(117) 評論(0)  編輯  收藏 所屬分類: hibernate
    主站蜘蛛池模板: 99久久免费国产香蕉麻豆| 免费无码又爽又刺激高潮软件| 亚洲人成免费电影| 亚洲一级二级三级不卡| 中国内地毛片免费高清| 亚洲中文字幕不卡无码| 久久国产美女免费观看精品| 国产亚洲美女精品久久久2020| 国产特黄一级一片免费 | 成人免费福利电影| 亚洲伊人色一综合网| 无码国产精品久久一区免费| 亚洲欧美日韩综合久久久| 免费a级黄色毛片| xvideos永久免费入口| 亚洲精品成人片在线播放| 日本高清免费观看| 亚洲伦理一二三四| 国产成人免费片在线观看| 国产精品极品美女自在线观看免费 | 国产免费午夜a无码v视频| 九九九国产精品成人免费视频| 亚洲人成色7777在线观看| 99xxoo视频在线永久免费观看| 亚洲乱码在线播放| 国产在线观看免费完整版中文版 | 亚洲成A∨人片在线观看无码| 毛片基地免费视频a| 特级毛片全部免费播放| 亚洲AV中文无码乱人伦下载| 免费观看美女用震蛋喷水的视频| 中文字幕在线观看亚洲日韩| 亚洲国产精品日韩| 曰批视频免费40分钟试看天天| 亚洲人成人网毛片在线播放| 国产精品V亚洲精品V日韩精品| 99re免费在线视频| 处破女第一次亚洲18分钟| 国产A在亚洲线播放| 在线免费观看一区二区三区| 久久久久免费视频|