Автор оригинала: Vivek Balasubramaniam.
1. введение
В этом уроке мы узнаем о составных первичных ключах и соответствующих аннотациях в JPA.
2. Составные Первичные Ключи
Составной первичный ключ – также называемый составным ключом – представляет собой комбинацию двух или более столбцов, образующих первичный ключ для таблицы.
В JPA у нас есть два варианта определения составных ключей: Аннотации @IdClass и @EmbeddedId .
Чтобы определить составные первичные ключи, мы должны следовать некоторым правилам:
- Составной класс первичного ключа должен быть открытым
- У него должен быть конструктор no-arg
- Он должен определить equals() и hashCode() методы
- Он должен быть S сериализуемым
3. Аннотация IdClass
Допустим, у нас есть таблица с именем Account и в ней есть два столбца – AccountNumber, AccountType– , которые образуют составной ключ. Теперь мы должны нанести его на карту в JPA.
В соответствии со спецификацией JPA давайте создадим класс Account Id с этими полями первичного ключа:
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() }
Далее давайте свяжем Идентификатор учетной записи класс с сущностью Учетная запись .
Для этого нам нужно аннотировать объект с помощью аннотации @IdClass . Мы также должны объявить поля из класса AccountId в сущности Account и аннотировать их с помощью @Id :
@Entity @IdClass(AccountId.class) public class Account { @Id private String accountNumber; @Id private String accountType; // other fields, getters and setters }
4. Аннотация EmbeddedId
@EmbeddedId является альтернативой аннотации @IdClass .
Давайте рассмотрим другой пример, в котором мы должны сохранить некоторую информацию о Книге с названием и языком в качестве полей первичного ключа.
В этом случае класс первичного ключа 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 }
Затем нам нужно встроить этот класс в сущность B ook , используя @EmbeddedId :
@Entity public class Book { @EmbeddedId private BookId bookId; // constructors, other fields, getters and setters }
5. @IdClass против @EmbeddedId
Как мы только что видели, разница на поверхности между этими двумя заключается в том , что с помощью @IdClass нам пришлось указать столбцы дважды – один раз в AccountId и снова в Account. Но с @EmbeddedId мы этого не сделали.
Однако есть и другие компромиссы.
Например, эти различные структуры влияют на запросы JPQL, которые мы пишем.
Например, с @IdClass запрос немного проще:
SELECT account.accountNumber FROM Account account
С помощью @EmbeddedId мы должны сделать один дополнительный обход:
SELECT book.bookId.title FROM Book book
Кроме того, @IdClass может быть весьма полезен в тех местах, где мы | используем составной ключевой класс, который мы не можем изменить.
Наконец, если мы собираемся получить доступ к частям составного ключа по отдельности, мы можем использовать @IdClass, но в местах, где мы часто используем полный идентификатор в качестве объекта, предпочтительнее использовать @EmbeddedId .
6. Заключение
В этой краткой статье мы рассмотрим составные первичные ключи в JPA.
Как всегда, полный код этой статьи можно найти на Github .