要映射复合键,可以使用EmbeddedId或IdClass注释。我知道这个问题不是严格地关于JPA,但是规范定义的规则也适用。所以他们在这里:
2.1.4 Primary Keys and Entity Identity
...
A composite primary key must
correspond to either a single
persistent field or property or to a
set of such fields or properties as
described below. A primary key class
must be defined to represent a
composite primary key. Composite
primary keys typically arise when
mapping from legacy databases when the
database key is comprised of several
columns. The EmbeddedId and
IdClass annotations are used to
denote composite primary keys. See
sections 9.1.14 and 9.1.15.
...
The following rules apply for
composite primary keys:
The primary key class must be public and must have a public no-arg
constructor.
If property-based access is used, the properties of the primary key
class must be public or protected.
The primary key class must be serializable.
The primary key class
must define equals and hashCode
methods. The semantics of value
equality for these methods must be
consistent with the database equality
for the database types to which the
key is mapped.
A composite primary key must either be represented and mapped as an
embeddable class (see Section 9.1.14,
“EmbeddedId Annotation”) or must be
represented and mapped to multiple
fields or properties of the entity
class (see Section 9.1.15, “IdClass
Annotation”).
If the composite primary key class is mapped to multiple fields or
properties of the entity class, the
names of primary key fields or
properties in the primary key class
and those of the entity class must
correspond and their types must be the
same.
使用id类
复合主键的类看起来像这样(可以是一个静态内部类):
public class TimePK implements Serializable {
protected Integer levelStation;
protected Integer confPathID;
public TimePK() {}
public TimePK(Integer levelStation, Integer confPathID) {
this.levelStation = levelStation;
this.confPathID = confPathID;
}
// equals, hashCode
}
以及实体:
@Entity
@IdClass(TimePK.class)
class Time implements Serializable {
@Id
private Integer levelStation;
@Id
private Integer confPathID;
private String src;
private String dst;
private Integer distance;
private Integer price;
// getters, setters
}
IdClass注释将多个字段映射到表PK。
与EmbeddedId
复合主键的类看起来像这样(可以是一个静态内部类):
@Embeddable
public class TimePK implements Serializable {
protected Integer levelStation;
protected Integer confPathID;
public TimePK() {}
public TimePK(Integer levelStation, Integer confPathID) {
this.levelStation = levelStation;
this.confPathID = confPathID;
}
// equals, hashCode
}
以及实体:
@Entity
class Time implements Serializable {
@EmbeddedId
private TimePK timePK;
private String src;
private String dst;
private Integer distance;
private Integer price;
//...
}
@EmbeddedId注释将一个PK类映射到表PK。
差异:
从物理模型的角度来看,两者没有区别
@EmbeddedId以某种方式更清楚地传达了键是复合键,当组合的pk本身是有意义的实体或在代码中重用时,IMO是有意义的。
@IdClass用于指定字段的某些组合是唯一的,但这些组合没有特殊含义。
它们还会影响你编写查询的方式(使它们变得更详细或更少):
与IdClass
从时间t开始选择t. levelstation
与EmbeddedId
select t. timepk . levelstation from Time t
参考文献
JPA 1.0规范
第2.1.4节主键和实体标识
EmbeddedId注释
章节9.1.15 IdClass注释