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

相关推荐