HIbernate有两种方法来处理复合主键,第一种是基于实体类属性的复合主键,另一种是基于主键类的复合主键。在这里使用基于主键类的复合主键。
通常将复合主键相关属性,单独抽取出来,建立一个独立的类,这个类就是主键类,要求:
* 必须实现序列化(Serializable)接口
* 必须重写equals和hashcode方法
复合主键的值是一个主键类,而不是一个普通的常见数值,因此,复合主键在映射文件中采用<composite-id>标签进行标识,其它属性采用<property>正常映射。
建立一个主键类Timestamp,代码如下:
public class Timestamp implements Serializable{
private String date;
private String time;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time
}
//重写equals方法
public boolean equals(Object other) {
if(this == other) {
return true;
}
if(other == null) {
return false;
}
if(!(other instanceof Timestamp)) {
return false;
}
Timestamp castOther = (Timestamp)other;
//根据业务需要,设定比较条件
return ((this.getDate() == castOther.getDate())
|| (this.getDate() != null && castOther.getDate() != null
&& this.getDate().equals(castOther.getDate())))
&& ((this.getTime() == castOther.getTime())
|| (this.getTime() != null && castOther.getTime() !=null
&& this.getTime().equals(castOther.getTime())));
}
//重写hashCode()方法
public int hashCode() {
int result = 17;
result = 37 * result +
(getDate() == null ? 0 : this.getDate().hashCode());
result = 37 * result +
(getTime() == null ? 0 : this.getTime().hashCode());
return result;
}
}
建立以主键类Timestamp为其中一个属性的bean类,代码如下:
public class Message implements Serializable {
private Timestamp timestamp;
private String messageId;
private String messageContent;
public Timestamp getTimestamp() {
return timestamp;
}
public void setTimestamp(Timestamp timestamp) {
this.timestamp = timestamp;
}
public String getMessageId() {
return messageId;
}
public void setMessageId(String messageId) {
this.messageId = messageId;
}
public String getMessageContent() {
return messageContent;
}
public void setMessageContent(String messageContent) {
this.messageContent = messageContent;
}
}
建立映射文件Message.hbm.xml,并在hibernate.cfg.xml文件中加入该映射文件,Message.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="com.iprai.hibernate.Message" table="message">
<composite-id name="timestamp">
<key-property name="date" column="idate"/>
<key-property name="time" column="itime"/>
</composite-id>
<property name="messageId" column="message_id"/>
<property name="messageContent" column="message_content"/>
</class>
</hibernate-mapping>
编写JUnit测试代码如下:
import java.util.Date;
import org.hibernate.Session;
import junit.framework.TestCase;
public class MessageTest extends TestCase {
public void testSave() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//复合主键
Timestamp timestamp = new Timestamp();
timestamp.setDate("2009-12-05");
timestamp.setTime("17:01:23");
Message message = new Message();
//和主键建立关联
message.setTimestamp(message);
message.setMessageId("01");
message.setMessageContent("JavaEye");
session.save(message);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
public void testLoad() {
Session session = null;
try {
session = HibernateUtils.getSession();
//复合主键
Timestamp timestamp = new Timestamp();
timestamp.setDate("2009-12-05");
timestamp.setTime("17:01:23");
Message message = (Message)session.load(Message.class, timestamp);
System.out.println("MessageId=" + message.getMessageId());
System.out.println("MessageContent=" + message.getMessageContent());
}catch(Exception e) {
e.printStackTrace();
}finally {
HibernateUtils.closeSession(session);
}
}
}