关系数据库实际上只支持多对一或一对一的单向关联。我们每次在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的多对一单向关系就可以了。