hibernate注解配置联合主键
有时一个实体的主键可能同时为多个,例如下面使用的字典“Dictionary”实体,需要通过dictId、dictTypeid和cityId来查找指定实体,当且仅当dictId、dictTypeid和cityId的值完全相同时,才认为是相同的实体对象。要配置这样的联合主键,步骤如以下所示。
(1)编写一个联合主键的类DictionaryPK,代码如下。
import java.io.Serializable; import javax.persistence.Column; /** * 字典表主键类(联合主键) * * @author ahomeeye */ public class DictionaryPK implements Serializable { private static final long serialVersionUID = -1118337265519377063L; private String dictId; // 数据标识 private String dictTypeid;// 数据类型标识 private String cityId;// 所属本地网 默认0 @Column(name = "DICT_ID") public String getDictId() { return dictId; } public void setDictId(String dictId) { this.dictId = dictId; } @Column(name = "DICT_TYPEID") public String getDictTypeid() { return dictTypeid; } public void setDictTypeid(String dictTypeid) { this.dictTypeid = dictTypeid; } @Column(name = "CITY_ID") public String getCityId() { return cityId; } public void setCityId(String cityId) { this.cityId = cityId; } public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + ((dictId == null) ? 0 : dictId.hashCode()); result = PRIME * result + ((dictTypeid == null) ? 0 : dictTypeid.hashCode()); result = PRIME * result + ((cityId == null) ? 0 : cityId.hashCode()); return result; } public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final DictionaryPK other = (DictionaryPK) obj; if (dictId == null) { if (other.dictId != null) return false; } else if (!dictId.equals(other.dictId)) return false; if (dictTypeid == null) { if (other.dictTypeid != null) return false; } else if (!dictTypeid.equals(other.dictTypeid)) return false; if (cityId == null) { if (other.cityId != null) return false; } else if (!cityId.equals(other.cityId)) return false; return true; } }
作为符合主键类,要满足以下几点要求:
1.必须实现Serializable接口。
2.必须有默认的public无参数的构造方法。
3.必须覆盖equals和hashCode方法。equals方法用于判断两个对象是否相同,EntityManger通过find方法来查找Entity时,是根据equals的返回值来判断的。本例中,只有对象的dictId、dictTypeid和cityId值完全相同时或同一个对象时则返回true,否则返回false。hashCode方法返回当前对象的哈希码,生成的hashCode相同的概率越小越好,算法可以进行优化。
(2)通过@IdClass注释在实体中标注联合主键,实体代码如下。
import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.IdClass; import javax.persistence.Table; /** * 系统字典数据 * * @author ahomeeye */ @Entity @Table(name = "T_DICT") @IdClass(DictionaryPK.class) public class Dictionary implements Serializable { private static final long serialVersionUID = 1L; private String dictId; // 数据标识 private String dictTypeid;// 数据类型标识 private String dictName;// 数据名称 private String dictStatus;// 数据状态 private String dictDesc;// 数据描述 private Integer dictOrder;// 序号 private String cityId;// 所属本地网 默认0 @Id @Column(name = "DICT_ID") public String getDictId() { return dictId; } public void setDictId(String dictId) { this.dictId = dictId; } @Id @Column(name = "DICT_TYPEID") public String getDictTypeid() { return dictTypeid; } public void setDictTypeid(String dictTypeid) { this.dictTypeid = dictTypeid; } @Column(name = "DICT_NAME") public String getDictName() { return dictName; } public void setDictName(String dictName) { this.dictName = dictName; } @Column(name = "DICT_STATUS") public String getDictStatus() { return dictStatus; } public void setDictStatus(String dictStatus) { this.dictStatus = dictStatus; } @Column(name = "DICT_DESC") public String getDictDesc() { return dictDesc; } public void setDictDesc(String dictDesc) { this.dictDesc = dictDesc; } @Column(name = "DICT_INDEX") public Integer getDictOrder() { return dictOrder; } public void setDictOrder(Integer dictOrder) { this.dictOrder = dictOrder; } @Id @Column(name = "CITY_ID") public String getCityId() { return cityId; } public void setCityId(String cityId) { this.cityId = cityId; } }
标注联合主键时需要注意以下几个问题。
1.@IdClass标注用于标注实体所使用主键规则的类。它的定义如下所示。
@Target({TYPE})@Retention(RUNTIME)
public@interfaceIdClass{
Classvalue();
}
2.属性Class表示联合主键所使用的类,本例中使用DictionaryPK这个联合主键类。
3.在实体中同时标注主键的属性。本例中在dictId、dictTypeid和cityId的getter方法前标注@Id,表示联合主键使用这两个属性。
(3)这样定义实体的联合主键后,通过以下代码便可以获得指定的实体对象:
DictionaryPK cpk = new DictionaryPK ("asyncTree","OperLogFunc","0"); Dictionary instance = entityManager.find(DictionaryPK .class, cpk);
参考:
http://www.blogjava.net/relax/archive/2009/09/18/295587.html