posts - 495,comments - 227,trackbacks - 0
          眾所周知,到了Hibernate3.0以后,關(guān)聯(lián)關(guān)系的對(duì)象默認(rèn)都是使用延遲加載,例 如<one-to-many>時(shí).但我在映射<one-to-one>,<many-to-one>關(guān)系時(shí)指定了 lazy="true",但是在查詢對(duì)象時(shí),我只想查詢一個(gè)對(duì)象,仍然會(huì)把這個(gè)對(duì)象所關(guān)聯(lián)的<one-to-one>,<many- to-one>對(duì)象一起查詢出來,這樣造成了極大的性能浪費(fèi).在不指定lazy屬性時(shí),<many-to-one>所關(guān)聯(lián)的對(duì)象反而會(huì) 延遲加載,這讓我大為困惑,還以為是Hibernate的bug.
          在網(wǎng)上查找資料,說在為了延遲加載<one-to-one>,<many-to-one>所關(guān)聯(lián)的對(duì)象,需要設(shè)置被關(guān)聯(lián)的對(duì)象<class name="" lazy="true">,我也這樣做了,但是仍然沒有效果.
          仔 細(xì)閱讀了Hibernate的手冊(cè),才發(fā)現(xiàn)原來要延遲加載<one-to-one>,<many-to-one>所關(guān)聯(lián)的對(duì)象 時(shí),除了要指定lazy="true"外,還需要運(yùn)行期字節(jié)碼增強(qiáng),而我省去了這一步,所以延遲加載沒有效果.同時(shí)還發(fā)現(xiàn)在默認(rèn)情況下,<one- to-one>,<many-to-one>的lazy屬性是"proxy"而不是"true"!因此如果直接采用lazy的默認(rèn)值, 是可以延遲加載的.
          總結(jié)一下:
          <many-to-one>默認(rèn)的屬性是lazy="proxy",此時(shí)默認(rèn)是會(huì)延遲加載的.在指定了lazy="true"之后,必須要經(jīng)過運(yùn)行期字節(jié)碼增加,延遲加載才有效果.
          而<one- to-one>相對(duì)要復(fù)雜一點(diǎn),延遲加載還要受到constrained屬性的限制.constrained="false"時(shí)表明實(shí)體和被關(guān)聯(lián)到 的實(shí)體的約束不是強(qiáng)制的,即存在一個(gè)實(shí)體時(shí),它通過<one-to-one>關(guān)聯(lián)的實(shí)體可能存在,也可能不存在,這時(shí)在查詢實(shí)體 時(shí),Hibernate總會(huì)發(fā)起一次查詢檢查<one-to-one>所關(guān)聯(lián)的實(shí)體是否存在,而這時(shí)已經(jīng)可以把one-to-one關(guān)聯(lián)的實(shí) 體查詢出來了,因此在<one-to-one>關(guān)系中,如果constrained="false",總是會(huì)立即加載關(guān)聯(lián)到的實(shí)體.
          如果當(dāng)constrained="true",且lazy="proxy"(默認(rèn)),是可以延遲加載的.
          如果當(dāng)constrained="true",且lazy="true"時(shí),需要經(jīng)過運(yùn)行期字節(jié)碼增加,延遲加載才會(huì)奏效.

          但是這里我還是有個(gè)疑問,既然在lazy="proxy"時(shí),已經(jīng)實(shí)現(xiàn)了延遲加載的效果,為什么在lazy="true"時(shí),還需要?jiǎng)討B(tài)字節(jié)碼增強(qiáng)才能實(shí)現(xiàn)延遲加載呢?


          Re: Hibernate中的延遲加載


          以后在one-to-one或many-to-one中不會(huì)再有l(wèi)azy="true"了,你可以理解成no-proxy.

          [1]起碼還是好的方向: 默認(rèn)就可以lazy了. 而且來了extra :)
          [2]寫Hibernate的哥們也是要活命的嘛, 不改變?cè)趺磥淼淖稍冑M(fèi), 不過Hibernate的migration寫的也還不錯(cuò).
          [3]constrained如你所說, 而且我估計(jì)這個(gè)屬性以后不會(huì)有太大變更.



          字節(jié)碼增強(qiáng)是一種基于你的配置和定義,在運(yùn)行時(shí)修改代碼的技術(shù)。有一個(gè)通用的代碼創(chuàng)建庫(kù)cglib,它允許延遲加載一個(gè)實(shí)現(xiàn)類,從而避免創(chuàng)建一 個(gè)需要延遲 加載的類型。Spring,iBatais,Hibernate這些框架都使用了這種技術(shù),即所謂的動(dòng)態(tài)代理。動(dòng)態(tài)代理有兩種方式:
          1)如果需要代理的類實(shí)現(xiàn)了一個(gè)接口,那么這些框架就在運(yùn)行時(shí)使用reflect反射機(jī)制來創(chuàng)建一個(gè)實(shí)現(xiàn)了此接口的類作為代理類。
          2)如果這個(gè)類沒有實(shí)現(xiàn)任何接口,那么就會(huì)使用cglib庫(kù)提供的方法來動(dòng)態(tài)創(chuàng)建一個(gè)此類的子類作為代理類。其實(shí)也是使用了反射機(jī)制。cglib就是處理第二種情況的一個(gè)通用框架。


          方法是:在主控方的<one-to-one>上加constrained=true,在被控方的class上加lazy=true,其實(shí)這個(gè)方法是可以的

          我們都知道,一對(duì)一有兩種實(shí)現(xiàn)方式,主鍵關(guān)聯(lián)和外鍵關(guān)聯(lián)

          主鍵關(guān)聯(lián):就是說兩個(gè)表的主鍵是一樣的
                              product(id,name)   image(id,name)
                              其中image的id引用product的id,product是主,image是次
          外鍵關(guān)聯(lián):就是說是通過一個(gè)字段引用另一個(gè)表的主鍵
                              product(id,name)   image(id,name,productid)
                              其中image的productid引用product的id,product是主,image是次

           

          在主鍵關(guān)聯(lián)時(shí),按如下進(jìn)行實(shí)體映射,是可以實(shí)現(xiàn)延遲加載的

          <hibernate-mapping package="onetoonebypk"> 
            
          <class name="Product1" table="product1"> 
              
          <id name="id" unsaved-value="null">
                
          <column name="id"></column>
                
          <generator class="uuid.hex"></generator>
              
          </id>
              
          <property name="name" column="name"></property>
               
          <one-to-one name="image1"
                          
          class="Image1"
                          cascade
          ="all"
                          constrained
          ="true"
                         
          >
              
          </one-to-one>

            
          </class> 

          </hibernate-mapping>

           

          <hibernate-mapping package="onetoonebypk"  > 
            
          <class name="Image1" table="image1" lazy="true"> 
              
          <id name="id">
                
          <generator class="foreign">
                  
          <param name="property">product1</param>
                
          </generator>
              
          </id>
              
          <property name="name" column="name"></property>
               
          <one-to-one name="product1"
                           class
          ="Product1"
                           cascade
          ="all">
              
          </one-to-one>
               
            
          </class> 

          </hibernate-mapping>

          當(dāng)使用外鍵關(guān)聯(lián)是,如果按如下方式編寫映射文件,使不能進(jìn)行延遲加載的

          <hibernate-mapping package="onetoonebyfk"  > 
            
          <class name="Image" table="image" lazy="true"> 
              
          <id name="id">
                
          <generator class="uuid.hex"/>
              
          </id>
              
          <property name="name" column="name"></property>
               
          <many-to-one name="product"
                           class
          ="Product"
                           unique
          ="true"
           
                           column
          ="productid">             
               
          </many-to-one>
            
          </class> 

          </hibernate-mapping>

          <hibernate-mapping package="onetoonebyfk"> 
            
          <class name="Product" table="product"> 
              
          <id name="id" unsaved-value="null">
                
          <column name="id"></column>
                
          <generator class="uuid.hex"></generator>
              
          </id>
              
          <property name="name" column="name"></property>
              
          <one-to-one name="image"
                          class
          ="Image"
                          cascade
          ="all"
                          constrained
          ="true"
                         property-ref
          ="product"
                          
          >
              
          </one-to-one>
            
          </class> 

          </hibernate-mapping>

          為什么呢,我認(rèn)為是在主方product中,有這樣一句話property-ref="product"

          這句話的意思是說加外鍵關(guān)聯(lián)類的屬性,如果不指定這個(gè)屬性,關(guān)聯(lián)類的主鍵就會(huì)被使用

          也就是說,如果不制定這個(gè),在查找image時(shí)就會(huì)使用
          select * from image where imageid==product_id 而不是
          select * from image where productid==product_id

          我們?cè)谥纏roduct_id的時(shí)候,需要找image中productid等于product_id記錄,而不是用image的主鍵作為比較

          去掉propery-def后,倒是可以延遲加載,但在讀取product.getImage()方法時(shí)會(huì)報(bào)沒有指定id記錄的異常,不過這也正常,我們?cè)趺茨苡胕mage的主鍵和product_id建立查詢條件呢

          至于為什么這樣,我不是很清楚

          總之:我目前的結(jié)論是:用主鍵關(guān)聯(lián),可以延遲加載,用外鍵關(guān)聯(lián),暫時(shí)不考慮延遲加載

          至于為什么,希望能到大家的幫助

          posted on 2011-11-09 22:05 SIMONE 閱讀(11174) 評(píng)論(6)  編輯  收藏 所屬分類: JAVA

          FeedBack:
          # re: 關(guān)于Hibernate一對(duì)一不能延遲加載的總結(jié)
          2011-11-10 14:26 | ii
          # re: 關(guān)于Hibernate一對(duì)一不能延遲加載的總結(jié)
          2011-11-10 14:26 | ii
          # re: 關(guān)于Hibernate一對(duì)一不能延遲加載的總結(jié)
          2011-11-10 14:27 | ii
          iiooiiooioioi@ii
            回復(fù)  更多評(píng)論
            
          # re: 關(guān)于Hibernate一對(duì)一不能延遲加載的總結(jié)
          2011-11-10 14:37 | tbw淘寶
          總結(jié)的不氏  回復(fù)  更多評(píng)論
            
          # re: 關(guān)于Hibernate一對(duì)一不能延遲加載的總結(jié)
          2015-09-30 14:00 | 一個(gè)陌生人
          # re: 關(guān)于Hibernate一對(duì)一不能延遲加載的總結(jié)
          2016-03-17 17:30 |
          <many-to-one name="person" class="Person" column="personid"
          property-ref="personId" cascade="all" unique="true" />

          上面的配置必定不能進(jìn)行延遲加載?  回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 双鸭山市| 宝山区| 湘潭市| 汝城县| 漠河县| 辽阳县| 油尖旺区| 海淀区| 涟水县| 贵德县| 寿光市| 曲靖市| 遵义市| 工布江达县| 正安县| 德钦县| 兴文县| 兰考县| 北流市| 余干县| 定南县| 莆田市| 保德县| 萝北县| 宁城县| 西丰县| 南木林县| 绿春县| 灵璧县| 威海市| 鄂托克旗| 绵阳市| 黄骅市| 柳州市| 嘉义县| 金门县| 商南县| 西盟| 沈丘县| 伊宁县| 墨江|