hibernate中复合主键的映射方式有两种。
1、基于实体类属性的复合主键
2、基于主键类的复合主键
两种映射方式的区别在于:第一种方式,主键字段和普通字段都在一个实体类中,第二种方式是单独将主键字段提取出来放到一个实体类中。
复合主键映射,主键所在的实体类,要实现Serializable接口,要覆盖hashCode()和equals()方法。
-------------------------------------------------------------
以表t_carInfo为例,t_carInfo中有字段carNo、carNoCategory、createTime三个字段,由carNo、carNoCategory构成复合主键。
1、 基于实体类属性的复合主键映射
只有一个实体类:carInfo,包含字段carNo、carNoCategory、createTime,并且,该实体类要实现Serializable接口,重写hashCode()和equals().
映射文件carInfo.hbm.xml:
<class name="carInfo" table="t_carInfo>
<composite-id>
<!-- key-property标签表示哪一些属性对应复合主键 -->
<key-property name="carNo" type="string />
<key-property name="carNoCategory" type="string" />
</composite-id>
<property name="createTime" type="Date" />
2. 基于逐渐类的复合主键映射
有实体类carInfo,字段为creteTime,carInfoPK类的引用;还有一个主键类carInfoPK,字段为carNo、carNoCategory,carInfoPK这个类要实现Serializable接口,要重写hashCode()和equals()方法。
一个映射文件carInfoPK.hbm.xml:
<class name="carInfo" table="t_carInfo">
<!--和第一种方式的区只在于,composite-id中需要用name指出主键对应的对象-->
<composite-id name="carInfoPK">
<key-property name="carNo"/>
<key-property name="carNoCategory"/>
</composite-id>
<property name="createTime" type="date"/>
</class>
复合主键映射,含有主键的类必须实现Serializable接口,还要覆盖equals()和hashCode()方法。这是符合主键映射同其他映射不同的地方。
实现Serializable接口,其原因在于:当我们使用get() 、load()方法查询数据时,Hibernate中定义的get()和load()方法的定义形式如下:
Object get( Class theClass , Serializable id)
Object load(Class theClass ,Serializable id)
get和load方法只提供了一个传递主键的参数,由于是复合主键,至少有两个参数,所以,只能传递包含复合主键的对象,而参数类型是Serializable类型的。这样,就理解了为什么包含复合主键的类要实现Serializable接口了吧!
Object load(Class theClass ,Serializable id)关于覆盖equals()和hashCode()方法,具体还是不太清楚。
这是覆盖equals和hashCode生成的代码:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((carNo == null) ? 0 : carNo.hashCode());
result = prime * result + ((carNoCategory == null) ? 0 : carNoCategory.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
FiscalYearPeriodPK other = (FiscalYearPeriodPK) obj;
if (carNo == null) {
if (other.carNo != null)
return false;
} else if (!carNo.equals(other.carNo))
return false;
if (carNoCategory == null) {
if (other.carNoCategory != null)
return false;
} else if (!carNoCategory.equals(other.carNoCategory))
return false;
return true;
}
关于为什么要重写equals()和hashCode()方法,目前还是不理解,先在这里标记个疑问,求讲解。