Java 我应该使用哪个注释:@IdClass 或 @EmbeddedId
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/212350/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Which annotation should I use: @IdClass or @EmbeddedId
提问by sakana
The JPA
(Java Persistence API) specification has 2 different ways to specify entity composite keys: @IdClass
and @EmbeddedId
.
的JPA
(Java持久性API)规范有2名不同的方式来指定实体组合键:@IdClass
和@EmbeddedId
。
I'm using both annotations on my mapped entities, but it turns out to be a big mess to people who aren't very familiar with JPA
.
我在我的映射实体上使用了这两个注释,但对于不太熟悉JPA
.
I want to adopt only one way to specify composite keys. Which one is really the best? Why?
我只想采用一种方式来指定复合键。哪一个真的是最好的?为什么?
采纳答案by Jorge Ferreira
I consider that @EmbeddedId
is probably more verbose because with @IdClass
you cannot access the entire primary key object using any field access operator. Using the @EmbeddedId
you can do like this:
我认为这@EmbeddedId
可能更冗长,因为@IdClass
您无法使用任何字段访问运算符访问整个主键对象。使用@EmbeddedId
你可以这样做:
@Embeddable class EmployeeId { name, dataOfBirth }
@Entity class Employee {
@EmbeddedId EmployeeId employeeId;
...
}
This gives a clear notion of the fields that make the composite key because they are all aggregated in a class that is accessed trough a field access operator.
这给出了构成复合键的字段的清晰概念,因为它们都聚集在一个通过字段访问运算符访问的类中。
Another difference with @IdClass
and @EmbeddedId
is when it comes to write HQL :
与@IdClass
and 的另一个区别@EmbeddedId
是在编写 HQL 时:
With @IdClass
you write:
和@IdClass
你一起写:
select e.name from Employee e
and with @EmbeddedId
you have to write:
与@EmbeddedId
你必须写:
select e.employeeId.name from Employee e
You have to write more text for the same query. Some may argue that this differs from a more natural language like the one promoted by IdClass
. But most of the times understanding right from the query that a given field is part of the composite key is of invaluable help.
您必须为同一查询编写更多文本。有些人可能会争辩说,这与更自然的语言(如IdClass
. 但是大多数情况下,从查询中直接理解给定字段是组合键的一部分是非常有用的。
回答by laz
I discovered an instance where I had to use EmbeddedId instead of IdClass. In this scenario there is a join table that has additional columns defined. I attempted to solve this problem using IdClass to represent the key of an entity that explicitly represents rows in the join table. I couldn't get it working this way. Thankfully "Java Persistence With Hibernate" has a section dedicated to this topic. One proposed solution was very similar to mine but it used EmbeddedId instead. I modeled my objects after those in the book it now behaves correctly.
我发现了一个必须使用 EmbeddedId 而不是 IdClass 的实例。在这种情况下,有一个连接表定义了额外的列。我尝试使用 IdClass 来表示实体的键来解决这个问题,该实体显式表示连接表中的行。我无法让它以这种方式工作。谢天谢地,“Java Persistence With Hibernate”有一节专门讨论这个主题。一个提议的解决方案与我的非常相似,但它使用了 EmbeddedId。我按照书中的对象建模我的对象,现在它的行为是正确的。
回答by bertie
I think the main advantage is that we could use @GeneratedValue
for the id when using the @IdClass
? I'm sure we can't use @GeneratedValue
for @EmbeddedId
.
我认为主要优点是我们可以@GeneratedValue
在使用@IdClass
? 我确定我们不能使用@GeneratedValue
for @EmbeddedId
。
回答by Ondrej Bozek
As far as i know if your composite PK contains FK it's easier and more straightforward to use @IdClass
据我所知,如果您的复合 PK 包含 FK,则使用起来更简单、更直接 @IdClass
With @EmbeddedId
you have to define mapping for your FK column twice, onece in @Embeddedable
and once for as i.e. @ManyToOne
where @ManyToOne
has to be read-only(@PrimaryKeyJoinColumn
) because you can't have one column set in two variables (possible conflicts).
So you have to set your FK using simple type in @Embeddedable
.
由于@EmbeddedId
您必须为 FK 列定义两次映射@Embeddedable
,一次输入一次,因为 IE @ManyToOne
where@ManyToOne
必须为只读(@PrimaryKeyJoinColumn
),因为您不能在两个变量中设置一列(可能发生冲突)。
所以你必须使用简单的类型来设置你的 FK @Embeddedable
。
On the other site using @IdClass
this situation can be handled much easier as shown in Primary Keys through OneToOne and ManyToOne Relationships:
在另一个站点上,使用@IdClass
这种情况可以更容易地处理,如通过 OneToOne 和 ManyToOne 关系的主键所示:
Example JPA 2.0 ManyToOne id annotation
示例 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;
...
}
Example JPA 2.0 id class
示例 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;
}
}
回答by B.K
Composite Key must not have an @Id
property when @EmbeddedId
is used.
复合键@Id
在@EmbeddedId
使用时不能有属性。
回答by Adelin
There are three strategies to use a compound primary key:
使用复合主键有以下三种策略:
- Mark it as
@Embeddable
and add to your entity class a normal property for it, marked with@Id
. - Add to your entity class a normal property for it, marked with
@EmbeddedId
. - Add properties to your entity class for all of its fields, mark them with
@Id
,and mark your entity class with@IdClass
, supplying the class of your primary key class.
- 将其标记为
@Embeddable
并将其添加到您的实体类的正常属性,标记为@Id
. - 为实体类添加一个普通属性,标有
@EmbeddedId
. - 将属性添加到您的实体类的所有字段,用 标记它们
@Id
,并用 标记您的实体类@IdClass
,提供主键类的类。
The use of @Id
with a class marked as @Embeddable
is the most natural approach. The @Embeddable
tag can be used for non-primary key embeddable values anyway. It allows you to treat the compound primary key as a single property, and it permits the reuse of the @Embeddable
class in other tables.
使用@Id
with 类标记为@Embeddable
是最自然的方法。@Embeddable
无论如何,该标签可用于非主键可嵌入值。它允许您将复合主键视为单个属性,并允许@Embeddable
在其他表中重用该类。
The next most natural approach is the use of the @EmbeddedId
tag. Here, the primary key class cannot be used in other tables since it is not an @Embeddable
entity, but it does allow us to treat the key as a
single attribute of some class.
下一个最自然的方法是使用@EmbeddedId
标签。在这里,主键类不能在其他表中使用,因为它不是@Embeddable
实体,但它允许我们将键视为某个类的单个属性。
Finally, the use of the @IdClass
and @Id
annotations allows us to map the compound primary key class using properties of the entity itself corresponding to the names of the properties in the primary key class. The names must correspond (there is no mechanism for overriding this), and the primary key class must honor the same obligations as with the other two techniques. The only advantage to this approach is its ability to “hide” the use of the primary key class from the interface of the enclosing entity. The @IdClass
annotation takes a value parameter of Class type, which must be the class to be used as the compound primary key. The fields that correspond to the properties of the primary key class to be used must all be annotated with @Id
.
最后,使用@IdClass
和@Id
注释允许我们使用实体本身的属性与主键类中的属性名称相对应来映射复合主键类。名称必须对应(没有覆盖它的机制),并且主键类必须遵守与其他两种技术相同的义务。这种方法的唯一优点是它能够从封闭实体的接口“隐藏”主键类的使用。该@IdClass
注解采用 Class 类型的值参数,该参数必须是要用作复合主键的类。与要使用的主键类的属性对应的字段必须全部使用@Id
.
Reference: http://www.apress.com/us/book/9781430228509
回答by Aleks Ben Maza
With EmbeddedId you can use the IN clause in HQL, for example : FROM Entity WHERE id IN :ids
where id is an EmbeddedId whereas it's pain to achieve the same result with IdClass you will want to do something like FROM Entity WHERE idPartA = :idPartA0 AND idPartB = :idPartB0 .... OR idPartA = :idPartAN AND idPartB = :idPartBN
使用 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