把这两种映射放到一起说,是因为这两种映射不像前面的复用型映射、数量和方向型映射那么分类鲜明,所以放到了这个“其他”里面。
在关系模型中,复合主键和其他的主键方式没有很大区别,但是反映到对象模型的配置上面,差别就比较大了:在对象模型中,复合主键需要一个独立的类,以下面把年和月作为复合主键为例:
import java.io.Serializable; public class FiscalYearPeriodPK implements Serializable { //核算年 private int fiscalYear; //核算月 private int fiscalPeriod; //省略getter和setter…… @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + fiscalPeriod; result = prime * result + fiscalYear; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final FiscalYearPeriodPK other = (FiscalYearPeriodPK) obj; if (fiscalPeriod != other.fiscalPeriod) return false; if (fiscalYear != other.fiscalYear) return false; return true; } }
主键类,必须要实现序列化接口,并复写hashCode()和equals()方法。
import java.util.Date; public class FiscalYearPeriod { private FiscalYearPeriodPK fiscalYearPeriodPK; //开始日期 private Date beginDate; //结束日期 private Date endDate; //状态 private String periodSts; //省略getter和setter…… }
主键类不需要独立的hbm文件,只需要为使用主键的类写映射文件即可:
<hibernate-mapping> <class name="com.tgb.hibernate.FiscalYearPeriod" table="t_fiscal_year_period"> <composite-id name="fiscalYearPeriodPK"> <key-property name="fiscalYear"/> <key-property name="fiscalPeriod"/> </composite-id> <property name="beginDate" type="date"/> <property name="endDate" type="date"/> <property name="periodSts"/> </class> </hibernate-mapping>
通过以上的配置,即可使用复合主键:
在集合映射中,Hibernate会为这类属性建立一张独立的表,用于存放这些数据,例如Set、List、Array、Map,以下以这些类型为例说明:
import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public class CollectionMapping { private int id; private String name; private Set setValues = new HashSet(); private List listValues = new ArrayList(); private String[] arrayValues; private Map mapValues; //省略getter和setter…… }
<hibernate-mapping> <class name="com.tgb.hibernate.CollectionMapping" table="t_collection_mapping"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <set name="setValues" table="t_set_values"> <key column="set_id"/> <element type="string" column="set_value" not-null="true"/> </set> <list name="listValues" table="t_list_values"> <key column="list_id"/> <list-index column="list_index"/> <element type="string" column="list_value"/> </list> <array name="arrayValues" table="t_array_values"> <key column="array_id"/> <list-index column="array_index"/> <element type="string" column="array_value"/> </array> <map name="mapValues" table="t_map_values"> <key column="map_id"/> <map-key type="string" column="map_key"/> <element type="string" column="map_value"/> </map> </class> </hibernate-mapping>
这里在除Set外的集合都加上了list-index属性,是因为数据在这些集合中的排列是有顺序的。
生成的表结构:
t_array_values
需要注意的是,虽然这些属性有自己的表,但它仍然是普通的属性。这表并非一张实体表,它没有自己的主键,可以算作一张伪表(一对一映射表也是),在加载时会立即加载,而不会延迟加载。
写到这里,加上前面的《Hibernate征途(四)之映射 序》、《Hibernate征途(五)之继承映射和组件映射》、《Hibernate征途(六)之数量和关系映射》常见的映射都已经写完,如果问题,欢迎斧正。