Chaves primárias compostas na JPA
1. Introdução
Neste tutorial, aprenderemos sobre chaves primárias compostas e as anotações correspondentes em JPA.
2. Chaves primárias compostas
Uma chave primária composta - também chamada de chave composta - é uma combinação de duas ou mais colunas para formar uma chave primária para uma tabela.
Em JPA, temos duas opções para definir as chaves compostas: As anotações@IdClasse@EmbeddedId.
Para definir as chaves primárias compostas, devemos seguir algumas regras:
-
A classe de chave primária composta deve ser pública
-
Ele deve ter um construtor sem argumento
-
Deve definir os métodosequals()ehashCode()
-
Deve serSerializable
3. A anotaçãoIdClass
Digamos que temos uma tabela chamadaAccount e ela tem duas colunas -accountNumber, accountType – que formam a chave composta. Agora temos que mapear na JPA.
De acordo com a especificação JPA, vamos criar uma classeAccountId com estes campos de chave primária:
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()
}
A seguir, vamos associar a classeAccountId à entidadeAccount.
Para fazer isso, precisamos anotar a entidade com a anotação@IdClass. Devemos também declarar os campos da classeAccountId na entidadeAccounte anotá-los com@Id:
@Entity
@IdClass(AccountId.class)
public class Account {
@Id
private String accountNumber;
@Id
private String accountType;
// other fields, getters and setters
}
4. A anotaçãoEmbeddedId
@EmbeddedId é uma alternativa para a anotação@IdClass.
Vamos considerar outro exemplo onde temos que persistir algumas informações de aBook comtitleelanguage como os campos de chave primária.
Neste caso, a classe de chave primária,BookId, must be annotated with @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
}
Então, precisamos incorporar essa classe na entidadeBook usando@EmbeddedId:
@Entity
public class Book {
@EmbeddedId
private BookId bookId;
// constructors, other fields, getters and setters
}
5. @IdClass vs@EmbeddedId
Como acabamos de ver, a diferença na superfície entre esses dois é que com@IdClass, tivemos que especificar as colunas duas vezes - uma vez emAccountIde novamente emAccount. Mas, com@EmbeddedId não.
Existem algumas outras vantagens, no entanto.
Por exemplo, essas diferentes estruturas afetam as consultas JPQL que escrevemos.
Por exemplo, com@IdClass, a consulta é um pouco mais simples:
SELECT account.accountNumber FROM Account account
Com@EmbeddedId, temos que fazer um percurso extra:
SELECT book.bookId.title FROM Book book
Além disso,@IdClass can be quite useful in places where weare using a composite key class that we can’t modify.
Finalmente, se vamos acessar partes da chave composta individualmente, podemos usar@IdClass,, masin places where we frequently use the complete identifier as an object, @EmbeddedId is preferred.
6. Conclusão
Neste artigo rápido, exploramos chaves primárias compostas no JPA.
Como sempre, o código completo para este artigo pode serfound over on Github.