1. Introduction
1.绪论
In this tutorial, we’ll learn about Composite Primary Keys and the corresponding annotations in JPA.
在本教程中,我们将学习JPA中的复合主键和相应的注释。
2. Composite Primary Keys
2.复合主键
A composite primary key, also called a composite key, is a combination of two or more columns to form a primary key for a table.
复合主键,也被称为复合键,是由两个或多个列组成的表的主键。
In JPA, we have two options to define the composite keys: the @IdClass and @EmbeddedId annotations.
在JPA中,我们有两个选项来定义复合键:@IdClass和@EmbeddedId注释。
In order to define the composite primary keys, we should follow some rules:
为了定义复合主键,我们应该遵循一些规则:。
- The composite primary key class must be public.
- It must have a no-arg constructor.
- It must define the equals() and hashCode() methods.
- It must be Serializable.
3. The IdClass Annotation
3.IdClass注释
Let’s say we have a table called Account and it has two columns, accountNumber and accountType, that form the composite key. Now we have to map it in JPA.
假设我们有一个名为Account的表,它有两列,accountNumber和accountType,构成复合键。现在我们必须在JPA中对其进行映射。
As per the JPA specification, let’s create an AccountId class with these primary key fields:
根据JPA规范,让我们创建一个带有这些主键字段的AccountId类。
public class AccountId implements Serializable {
private String accountNumber;
private String accountType;
// default constructor
public AccountId(String accountNumber, String accountType) {
this.accountNumber = accountNumber;
this.accountType = accountType;
}
// equals() and hashCode()
}
Next let’s associate the AccountId class with the entity Account.
接下来让我们将AccountId类与实体Account联系起来。
In order to do that, we need to annotate the entity with the @IdClass annotation. We must also declare the fields from the AccountId class in the entity Account and annotate them with @Id:
为了做到这一点,我们需要用@IdClass 注解来注释该实体。我们还必须在实体Account中声明AccountId类中的字段,并用@Id注释它们。
@Entity
@IdClass(AccountId.class)
public class Account {
@Id
private String accountNumber;
@Id
private String accountType;
// other fields, getters and setters
}
4. The EmbeddedId Annotation
4.EmbeddedId注释
@EmbeddedId is an alternative to the @IdClass annotation.
@EmbeddedId是@IdClass注解的一个替代。
Let’s consider another example where we have to persist some information of a Book, with title and language as the primary key fields.
让我们考虑另一个例子,我们必须持久化一个书的一些信息,标题和语言是主键字段。
In this case, the primary key class, BookId, must be annotated with @Embeddable:
在这种情况下,主键类,BookId,必须用@Embeddable来注释。
@Embeddable
public class BookId implements Serializable {
private String title;
private String language;
// default constructor
public BookId(String title, String language) {
this.title = title;
this.language = language;
}
// getters, equals() and hashCode() methods
}
Then we need to embed this class in the Book entity using @EmbeddedId:
然后我们需要在Book实体中使用@EmbeddedId嵌入这个类。
@Entity
public class Book {
@EmbeddedId
private BookId bookId;
// constructors, other fields, getters and setters
}
5. @IdClass vs @EmbeddedId
5.@IdClass vs @EmbeddedId
As we can see, the difference on the surface between these two is that with @IdClass we had to specify the columns twice, once in AccountId and again in Account; however, with @EmbeddedId we didn’t.
正如我们所看到的,这两者之间表面上的区别是,使用@IdClass时,我们必须指定两次列,一次在AccountId中,另一次在Account中;然而,使用@EmbeddedId时,我们没有。
There are some other trade offs though.
但也有一些其他的交换条件。
For example, these different structures affect the JPQL queries that we write.
例如,这些不同的结构会影响我们编写的JPQL查询。
With @IdClass, the query is a bit simpler:
有了@IdClass,查询就比较简单了。
SELECT account.accountNumber FROM Account account
With @EmbeddedId, we have to do one extra traversal:
使用@EmbeddedId,我们必须做一个额外的遍历。
SELECT book.bookId.title FROM Book book
Also, @IdClass can be quite useful in places where we are using a composite key class that we can’t modify.
另外,@IdClass在我们使用一个不能修改的复合键类的地方,可以相当有用。
If we’re going to access parts of the composite key individually, we can make use of @IdClass, but in places where we frequently use the complete identifier as an object, @EmbeddedId is preferred.
如果我们要单独访问复合键的部分,我们可以使用@IdClass,但是在我们经常使用完整标识符作为对象的地方,@EmbeddedId是首选。
6. Conclusion
6.结语
In this brief article, we explored composite primary keys in JPA.
在这篇简短的文章中,我们探讨了JPA中的复合主键。
As always, the complete code for this article can be found over on Github.
一如既往,本文的完整代码可以在Github上找到。