Answers:
我认为这@EmbeddedId
可能更冗长,因为@IdClass
无法使用任何字段访问运算符来访问整个主键对象。使用,@EmbeddedId
您可以这样做:
@Embeddable class EmployeeId { name, dataOfBirth }
@Entity class Employee {
@EmbeddedId EmployeeId employeeId;
...
}
这给构成组合键的字段提供了清晰的概念,因为它们全部聚集在通过字段访问运算符访问的类中。
与@IdClass
和的另一个不同@EmbeddedId
之处是编写HQL时:
与@IdClass
你一起写:
从员工e中选择e.name
和@EmbeddedId
你一起写:
从员工e中选择e.employeeId.name
您必须为同一查询写更多文本。有人可能会认为这与一种更自然的语言有所不同,例如由提倡的语言IdClass
。但是大多数时候,从查询中正确了解给定字段是组合键的一部分是非常有用的。
@IdClass
由@Gaurav给出的注解是非常原因,JPA规范列表创建复合键的两种方法.. @IdClass
和@EmbeddidId
有三种使用复合主键的策略:
@Embeddable
并为其添加一个普通属性(标记为)@Id
。@EmbeddedId
。@Id
,并用标记您的实体类@IdClass
,以提供主键类的类。使用@Id
标记为的类@Embeddable
是最自然的方法。@Embeddable
无论如何,该标记可用于非主键可嵌入值。它允许您将复合主键视为单个属性,并允许@Embeddable
在其他表中重用该类。
第二种最自然的方法是使用@EmbeddedId
标签。在这里,主键类不是@Embeddable
实体,因此不能在其他表中使用,但是它确实允许我们将键视为某个类的单个属性。
最后,@IdClass
和@Id
注释的使用允许我们使用与主键类中的属性名称相对应的实体本身的属性来映射复合主键类。名称必须对应(没有机制可以覆盖它),并且主键类必须遵守与其他两种技术相同的义务。这种方法的唯一优点是它能够从封闭实体的接口“隐藏”主键类的使用。的@IdClass
批注采用类类型的值参数,该参数必须是类被用作化合物主键。与要使用的主键类的属性相对应的字段必须全部用注释@Id
。
据我所知,您的复合PK是否包含FK,使用起来更简单,更直接 @IdClass
随着@EmbeddedId
你要定义你的FK列映射了两次,onece在@Embeddedable
一次用于为即@ManyToOne
哪里@ManyToOne
有只读(@PrimaryKeyJoinColumn
),因为你不能有两个变量(可能发生的冲突)一个集。
因此,您必须使用中的简单类型来设置FK @Embeddedable
。
在另一个站点上,通过OneToOne和ManyToOne关系@IdClass
显示在主键中,可以更轻松地处理这种情况:
JPA 2.0 ManyToOne id注释示例
...
@Entity
@IdClass(PhonePK.class)
public class Phone {
@Id
private String type;
@ManyToOne
@Id
@JoinColumn(name="OWNER_ID", referencedColumnName="EMP_ID")
private Employee owner;
...
}
JPA 2.0 id类示例
...
public class PhonePK {
private String type;
private long owner;
public PhonePK() {}
public PhonePK(String type, long owner) {
this.type = type;
this.owner = owner;
}
public boolean equals(Object object) {
if (object instanceof PhonePK) {
PhonePK pk = (PhonePK)object;
return type.equals(pk.type) && owner == pk.owner;
} else {
return false;
}
}
public int hashCode() {
return type.hashCode() + owner;
}
}
使用EmbeddedId,您可以在HQL中使用IN子句,例如:FROM Entity WHERE id IN :ids
其中id是EmbeddedId,而要使用IdClass达到相同的结果则很麻烦,您将需要执行以下操作FROM Entity WHERE idPartA = :idPartA0 AND idPartB = :idPartB0 .... OR idPartA = :idPartAN AND idPartB = :idPartBN
@IdClass
即使我@EmbeddedId
在大多数情况下都比较喜欢(可以从Antonio Goncalves的一次会议中了解到这一点。他建议@IdClass
在复合的情况下可以使用键类是无法访问或从其它模块或遗留代码,我们不能添加注释。在这些情况进来@IdClass
会给我们一个方式我们。