關聯式資料庫實際上只支援多對一或一對一的單向關聯。我們每次在hbm和持久化類中都對外來鍵做雙向設定實際是多餘的,如:
Cardparameter.java
- /**註冊卡資訊**/
- private Cardinfo cardinfo;
Cardparameter.hbm.xml
- <many-to-one name="cardinfo" class="com.telezone.domain.Cardinfo" fetch="select">
- <column name="CARDID" precision="22" scale="0" not-null="true" />
- </many-to-one>
Cardinfo.hbm.xml
- <set name="cardparameters" inverse="true" cascade="delete">
- <key>
- <column name="CARDID" precision="22" scale="0"
- not-null="true" />
- </key>
- <one-to-many class="com.telezone.domain.Cardparameter" />
- </set>
Cardinfo.java
- /**卡引數即卡狀態資訊集合**/
- private Set<Cardparameter> cardparameters = new HashSet<Cardparameter>(0);
而我們專案中,並沒有通過cardinfo取過它對應的所有cardparameter,都是根據cardid寫sql去資料庫查詢的……而且每次載入一個物件,會載入很多set物件到記憶體中,也很浪費吧。
比如cardinfo中很多set集合屬性:
- /**區域定位資訊集合**/
- private Set<Arealocatedata> arealocatedatas = new HashSet<Arealocatedata>(0);
- /**簡訊集合**/
- private Set<Smsinfo> smsinfos = new HashSet<Smsinfo>(0);
- /**報警設定資訊集合**/
- private Set<Alarmsetinfo> alarmsetinfos = new HashSet<Alarmsetinfo>(0);
- /**卡餘額資訊集合**/
- private Set<Cardbalance> cardbalances = new HashSet<Cardbalance>(0);
- /**套餐餘量資訊集合**/
- private Set<Premaininfo> premaininfos = new HashSet<Premaininfo>(0);
- /**卡物件資訊集合**/
- private Set<Cardownerinfo> cardownerinfos = new HashSet<Cardownerinfo>(0);
- /**報警資訊集合**/
- private Set<Alarmrecord> alarmrecords = new HashSet<Alarmrecord>(0);
- /**朋友資訊集合**/
- private Set<Friendinfo> friendinfos = new HashSet<Friendinfo>(0);
- /**卡引數即卡狀態資訊集合**/
- private Set<Cardparameter> cardparameters = new HashSet<Cardparameter>(0);
- /**卡交易資訊集合**/
- private Set<Cardtrade> cardtrades = new HashSet<Cardtrade>(0);
- /**卡與服務繫結資訊集合**/
- private Set<Cardserviceinfo> cardserviceinfos = new HashSet<Cardserviceinfo>(0);
- /**卡與手機繫結資訊集合**/
- private Set<Cardphoneinfo> cardphoneinfos = new HashSet<Cardphoneinfo>(0);
- /**實時定位資訊集合**/
- private Set<Locatedata> locatedatas = new HashSet<Locatedata>(0);
如果每次載入一個cardinfo物件,就會把所有一對多的資料都會載入到記憶體中,尤其是資料量很大的實時定位資料,那太恐怖了!!
為了驗證每次載入cardinfo物件時,是不是所有一對多的資料都會載入到記憶體中,我進行了測試,去獲得cardinfo的cardparameters集合,結果取不出來cardparameters報錯:
- failed to lazily initialize a collection of role: com.telezone.domain.Cardinfo.alarmrecords, no session or session was closed
為什麼專案中的沒載入進來而且報錯呢?
因為開啟了延遲載入,查詢cardinfo時並沒有主動載入所關聯的cardparameters,也就是說,當用到另一個表的資料時,再去資料庫中查詢該表的資料。但是這個查詢還需要使用之前查詢所使用的連線。
關閉延遲載入的方法是加入lazy=”false”
- <set name="cardparameters" inverse="true" lazy="false" cascade="delete">
- <key>
- <column name="CARDID" precision="22" scale="0" />
- </key>
- <one-to-many class="com.telezone.domain.Cardparameter" />
- </set>
然後就能得到cardinfo的cardparameters了。
驗證了可以取到,但這種同時取出的做法十分不明智。也就是說我們不需要設定Cardinfo的一對多關係。只設定Cardparameter的多對一單向關係就可以了。