關聯式資料庫實際上只支援多對一或一對一的單向關聯。我們每次在hbm和持久化類中都對外來鍵做雙向設定實際是多餘的,如:

Cardparameter.java

  1. /**註冊卡資訊**/ 
  2.     private Cardinfo cardinfo; 

Cardparameter.hbm.xml

  1. <many-to-one name="cardinfo" class="com.telezone.domain.Cardinfo" fetch="select"> 
  2.             <column name="CARDID" precision="22" scale="0" not-null="true" /> 
  3.         </many-to-one> 
  4.  

Cardinfo.hbm.xml

  1. <set name="cardparameters" inverse="true" cascade="delete"> 
  2.             <key> 
  3.                 <column name="CARDID" precision="22" scale="0" 
  4.                     not-null="true" /> 
  5.             </key> 
  6.             <one-to-many class="com.telezone.domain.Cardparameter" /> 
  7.         </set> 

Cardinfo.java

  1. /**卡引數即卡狀態資訊集合**/ 
  2.     private Set<Cardparameter> cardparameters = new HashSet<Cardparameter>(0); 

而我們專案中,並沒有通過cardinfo取過它對應的所有cardparameter,都是根據cardid寫sql去資料庫查詢的……而且每次載入一個物件,會載入很多set物件到記憶體中,也很浪費吧。

比如cardinfo中很多set集合屬性:

  1. /**區域定位資訊集合**/ 
  2.     private Set<Arealocatedata> arealocatedatas = new HashSet<Arealocatedata>(0); 
  3.     /**簡訊集合**/ 
  4.     private Set<Smsinfo> smsinfos = new HashSet<Smsinfo>(0); 
  5.     /**報警設定資訊集合**/ 
  6.     private Set<Alarmsetinfo> alarmsetinfos = new HashSet<Alarmsetinfo>(0); 
  7.     /**卡餘額資訊集合**/ 
  8.     private Set<Cardbalance> cardbalances = new HashSet<Cardbalance>(0); 
  9.     /**套餐餘量資訊集合**/ 
  10.     private Set<Premaininfo> premaininfos = new HashSet<Premaininfo>(0); 
  11.     /**卡物件資訊集合**/ 
  12.     private Set<Cardownerinfo> cardownerinfos = new HashSet<Cardownerinfo>(0); 
  13.     /**報警資訊集合**/ 
  14.     private Set<Alarmrecord> alarmrecords = new HashSet<Alarmrecord>(0); 
  15.     /**朋友資訊集合**/ 
  16.     private Set<Friendinfo> friendinfos = new HashSet<Friendinfo>(0); 
  17.     /**卡引數即卡狀態資訊集合**/ 
  18.     private Set<Cardparameter> cardparameters = new HashSet<Cardparameter>(0); 
  19.     /**卡交易資訊集合**/ 
  20.     private Set<Cardtrade> cardtrades = new HashSet<Cardtrade>(0); 
  21.     /**卡與服務繫結資訊集合**/ 
  22.     private Set<Cardserviceinfo> cardserviceinfos = new HashSet<Cardserviceinfo>(0); 
  23.     /**卡與手機繫結資訊集合**/ 
  24.     private Set<Cardphoneinfo> cardphoneinfos = new HashSet<Cardphoneinfo>(0); 
  25.     /**實時定位資訊集合**/ 
  26.     private Set<Locatedata> locatedatas = new HashSet<Locatedata>(0); 

如果每次載入一個cardinfo物件,就會把所有一對多的資料都會載入到記憶體中,尤其是資料量很大的實時定位資料,那太恐怖了!!

為了驗證每次載入cardinfo物件時,是不是所有一對多的資料都會載入到記憶體中,我進行了測試,去獲得cardinfo的cardparameters集合,結果取不出來cardparameters報錯:

  1. failed to lazily initialize a collection of role: com.telezone.domain.Cardinfo.alarmrecords, no session or session was closed 

為什麼專案中的沒載入進來而且報錯呢?

因為開啟了延遲載入,查詢cardinfo時並沒有主動載入所關聯的cardparameters也就是說,當用到另一個表的資料時,再去資料庫中查詢該表的資料。但是這個查詢還需要使用之前查詢所使用的連線。

關閉延遲載入的方法是加入lazy=”false”

  1. <set name="cardparameters" inverse="true" lazy="false" cascade="delete">  
  2.             <key>  
  3.                 <column name="CARDID" precision="22" scale="0" />  
  4.             </key>  
  5.             <one-to-many class="com.telezone.domain.Cardparameter" />  
  6.    </set>  

然後就能得到cardinfo的cardparameters了。

驗證了可以取到,但這種同時取出的做法十分不明智。也就是說我們不需要設定Cardinfo的一對多關係。只設定Cardparameter的多對一單向關係就可以了。