一、简介
- 复合主键映射其实应该算组件映射的一种特例,只是将相同字段抽取出来作为联合主键的字段。
- 通常将复合主键相关的属性,单独放到一个类中:
- 此类必须实现序列化接口
- 覆写hashCode和equals方法,保证主键唯一
二、实例(工程hibernate_composite_mapping
)
相关映射:
FiscalYearPeriod.java
private FiscalYearPeriodPK fiscalYearPeriodPK;
//开始日期
private Date beginDate;
//结束日期
private Date endDate;
//状态
private String periodSts;
FiscalYearPeriodPK.java
package cn.itcast.hibernate;
import java.io.Serializable;
public class FiscalYearPeriodPK implements Serializable {
//核算年
private int fiscalYear;
//核算月
private int fiscalPeriod;
public int getFiscalYear() {
return fiscalYear;
}
public void setFiscalYear(int fiscalYear) {
this.fiscalYear = fiscalYear;
}
public int getFiscalPeriod() {
return fiscalPeriod;
}
public void setFiscalPeriod(int fiscalPeriod) {
this.fiscalPeriod = fiscalPeriod;
}
@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;
}
}
FiscalYearPeriod.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="cn.itcast.hibernate.FiscalYearPeriod" table="_fiscal_year_period">
<composite-id name="fiscalYearPeriodPK">
<key-property name="fiscalYear"/>
<key-property name="fiscalPeriod"/>
</composite-id>
<property name="beginDate"/>
<property name="endDate"/>
<property name="periodSts"/>
</class>
</hibernate-mapping>
说明:这里我们给出的是实际项目中有些业务需要定期核算,比如按月核算,那么某年某月的核算结果就只能有一个,于是我们将年和月作为一个联合主键。
测试:
CompositeMappingTest.java
package cn.itcast.hibernate;
import java.util.Date;
import org.hibernate.Session;
import junit.framework.TestCase;
public class CompositeMappingTest extends TestCase {
public void testSave1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
FiscalYearPeriod fiscalYearPeriod = new FiscalYearPeriod();
FiscalYearPeriodPK pk = new FiscalYearPeriodPK();
pk.setFiscalYear(2008);
pk.setFiscalPeriod(8);
fiscalYearPeriod.setFiscalYearPeriodPK(pk);
fiscalYearPeriod.setBeginDate(new Date());
fiscalYearPeriod.setEndDate(new Date());
fiscalYearPeriod.setPeriodSts("Y");
session.save(fiscalYearPeriod);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
public void testLoad1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
FiscalYearPeriodPK pk = new FiscalYearPeriodPK();
pk.setFiscalYear(2008);
pk.setFiscalPeriod(8);
FiscalYearPeriod fiscalYearPeriod = (FiscalYearPeriod)session.load(FiscalYearPeriod.class, pk);
System.out.println(fiscalYearPeriod.getPeriodSts());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
}
说明:这里可以看到其存储方式和组件映射类似,只是在加载的时候我们可能麻烦点,需要分别给两个主键赋值之后去查询。
注意:现在不推荐使用此类主键,因为其和业务语义结合的太紧密,一旦业务发生变化,需要的改动很大,所以我们一般建议使用和业务语义无关的字段作为联合主键。同时在存储和加载的时候需要自己手动配置主键。