Claves primarias compuestas en JPA

Introducción

En este tutorial, aprenderemos sobre las Claves Primarias compuestas y las anotaciones correspondientes en JPA.

Claves primarias compuestas

Una clave primaria compuesta, también llamada clave compuesta, es una combinación de dos o más columnas para formar una clave primaria para una tabla.

En JPA, tenemos dos opciones para definir las claves compuestas: Las anotaciones @IdClass y @EmbeddedId.

Para definir las claves primarias compuestas, debemos seguir algunas reglas:

  • La clase de clave primaria compuesta debe ser pública
  • Debe tener un constructor no-arg
  • Debe definir los métodos equals() y hashCode ()
  • Debe ser Serializable

La anotación IdClass

digamos que tenemos una tabla llamada Cuenta y tiene dos columnas – Número de cuenta, tipo de cuenta – que forman la clave compuesta. Ahora tenemos que mapearlo en JPA.

De acuerdo con la especificación JPA, vamos a crear una clase accountId con estos campos de clave primaria:

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 continuación, asociemos la clase accountId con la Cuenta de entidad.

Para hacer eso, necesitamos anotar la entidad con la anotación @IdClass. También debemos declarar los campos de la clase accountId en la Cuenta de entidad y anotarlos con @Id:

@Entity@IdClass(AccountId.class)public class Account { @Id private String accountNumber; @Id private String accountType; // other fields, getters and setters}

La anotación EmbeddedId

@EmbeddedId es una alternativa a la anotación @IdClass.

Consideremos otro ejemplo en el que tenemos que conservar cierta información de un libro con el título y el idioma como campos clave principales.

En este caso, la clase de clave primaria, BookID, debe estar anotada con @Embeddable:

@Embeddablepublic 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}

Luego, necesitamos incrustar esta clase en la entidad del libro usando @EmbeddedId:

@Entitypublic class Book { @EmbeddedId private BookId bookId; // constructors, other fields, getters and setters}

@IdClass vs @ EmbeddedId

Como acabamos de ver, la diferencia en la superficie entre estos dos es que con @IdClass, tuvimos que especificar las columnas dos veces, una en accountId y otra en Account. Pero, con @EmbeddedId no lo hicimos.

Sin embargo, hay algunas otras compensaciones.

Por ejemplo, estas diferentes estructuras afectan a las consultas JPQL que escribimos.

Por ejemplo, con @IdClass, la consulta es un poco más simple:

SELECT account.accountNumber FROM Account account

Con @EmbeddedId, tenemos que hacer un recorrido adicional:

SELECT book.bookId.title FROM Book book

Además, @IdClass puede ser bastante útil en lugares donde estamos usando una clase de clave compuesta que no podemos modificar.

Finalmente, si vamos a acceder a partes de la clave compuesta individualmente, podemos hacer uso de @IdClass, pero en lugares donde usamos con frecuencia el identificador completo como objeto, se prefiere @EmbeddedId.

Conclusión

En este artículo rápido, exploramos las claves primarias compuestas en JPA.

Como siempre, el código completo de este artículo se puede encontrar en Github.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.