我创建了一个使用@Id指向@Embeddable复合键的实体。我认为一切正常。但是,据我所知,在将@Id切换为@EmbeddedId之后,一切仍然可以正常工作。
之前:
@Entity public final class MyEntity { private CompoundKey id; @Id public CompoundKey getId() { return id; } public void setId(CompoundKey id) { this.id = id; }
后:
@Entity public final class MyEntity { private CompoundKey id; @EmbeddedId public CompoundKey getId() { return id; } public void setId(CompoundKey id) { this.id = id; }
引用复合键时,使用@Id和@EmbeddedId批注之间有区别吗?
实际上,我对 “之前” 版本的工作感到惊讶。根据规范,映射您的Embeddable复合键的正确方法是 “之后” 版本。引用JPA 1.0规范:
Embeddable
2.1.4主键和实体身份 每个实体必须有一个主键。 必须在作为实体层次结构根目录的实体上或在实体层次结构的映射超类上定义主键。在实体层次结构中,主键必须定义一次。 一个简单的(即非复合的)主键必须对应于实体类的单个持久字段或属性。 该Id注释被用来表示一个简单的主键。 请参阅第9.1.8节。 复合主键必须对应于单个持久性字段或属性,或对应于如下所述的一组此类字段或属性。必须定义一个主键类来表示一个复合主键。当数据库键由几列组成时,从主数据库进行映射时,通常会出现复合主键。 的EmbeddedId和和 IdClass注解用于表示复合主键。参见9.1.14和9.1.15节。 主键(或复合主键的字段或属性)应为以下类型之一:任何Java原语类型;任何原始包装器类型;java.lang.String; java.util.Date; java.sql.Date。但是,一般来说,近似数字类型(例如浮点类型)绝对不能在主键中使用。主键使用其他类型的实体将不可移植。如果使用生成的主键,则仅整数类型是可移植的。如果java.util.Date用作主键字段或属性,则应将时间类型指定为DATE。 …
每个实体必须有一个主键。
必须在作为实体层次结构根目录的实体上或在实体层次结构的映射超类上定义主键。在实体层次结构中,主键必须定义一次。
一个简单的(即非复合的)主键必须对应于实体类的单个持久字段或属性。 该Id注释被用来表示一个简单的主键。 请参阅第9.1.8节。
Id
复合主键必须对应于单个持久性字段或属性,或对应于如下所述的一组此类字段或属性。必须定义一个主键类来表示一个复合主键。当数据库键由几列组成时,从主数据库进行映射时,通常会出现复合主键。 的EmbeddedId和和 IdClass注解用于表示复合主键。参见9.1.14和9.1.15节。
EmbeddedId
IdClass
主键(或复合主键的字段或属性)应为以下类型之一:任何Java原语类型;任何原始包装器类型;java.lang.String; java.util.Date; java.sql.Date。但是,一般来说,近似数字类型(例如浮点类型)绝对不能在主键中使用。主键使用其他类型的实体将不可移植。如果使用生成的主键,则仅整数类型是可移植的。如果java.util.Date用作主键字段或属性,则应将时间类型指定为DATE。
java.lang.String
java.util.Date
java.sql.Date
…
然后:
9.1.14 EmbeddedId注释 该EmbeddedId注释被施加到一个实体类的持久字段或属性或映射超表示一个复合主密钥是一个可嵌入类。可嵌入类的注释必须为 Embeddable。 使用EmbeddedId 注释时,只能有一个注释,没有Id注释EmbeddedId。
该EmbeddedId注释被施加到一个实体类的持久字段或属性或映射超表示一个复合主密钥是一个可嵌入类。可嵌入类的注释必须为 Embeddable。
使用EmbeddedId 注释时,只能有一个注释,没有Id注释EmbeddedId。