Перейти к основному содержимому

Определение уникальных ограничений в JPA

· 8 мин. чтения

1. Введение

В этом руководстве мы обсудим определение уникальных ограничений с помощью JPA и Hibernate .

Сначала мы рассмотрим уникальные ограничения и то, чем они отличаются от ограничений первичного ключа.

Затем мы рассмотрим важные аннотации JPA, @ Column(unique=true) и @UniqueConstraint. Мы реализуем их, чтобы определить уникальные ограничения для одного столбца и нескольких столбцов.

Наконец, мы узнаем, как определить уникальные ограничения для столбцов таблицы, на которые ссылаются.

2. Уникальные ограничения

Давайте начнем с краткого обзора. Уникальный ключ — это набор из одного или нескольких столбцов таблицы, которые однозначно идентифицируют запись в таблице базы данных.

Как ограничения уникальности, так и ограничения первичного ключа гарантируют уникальность столбца или набора столбцов.

2.1. Чем это отличается от ограничений первичного ключа?

Уникальные ограничения гарантируют, что данные в столбце или комбинации столбцов уникальны для каждой строки. Например, первичный ключ таблицы действует как неявное ограничение уникальности. Следовательно, ограничение первичного ключа автоматически имеет уникальное ограничение.

Кроме того, у нас может быть только одно ограничение первичного ключа на таблицу. Однако для каждой таблицы может быть несколько уникальных ограничений.

Проще говоря, уникальные ограничения применяются в дополнение к любым ограничениям, связанным с отображением первичного ключа.

Уникальные ограничения, которые мы определяем, используются во время создания таблицы для создания правильных ограничений базы данных, а также могут использоваться во время выполнения для заказа операторов вставки , обновления или удаления .

2.2. Что такое одностолбцовые и многостолбцовые ограничения?

Уникальное ограничение может быть либо ограничением столбца, либо ограничением таблицы. На уровне таблицы мы можем определить уникальные ограничения для нескольких столбцов.

JPA позволяет нам определять уникальные ограничения в нашем коде, используя @Column(unique=true) и @UniqueConstraint . Эти аннотации интерпретируются процессом генерации схемы, автоматически создавая ограничения.

Прежде всего, мы должны подчеркнуть, что ограничения уровня столбца применяются к одному столбцу, а ограничения уровня таблицы применяются ко всей таблице.

Мы обсудим это более подробно в следующих разделах.

3. Настройте сущность

Сущность в JPA представляет собой таблицу, хранящуюся в базе данных . Каждый экземпляр сущности представляет собой строку в таблице.

Начнем с создания объекта домена и сопоставления его с таблицей базы данных. В этом примере мы создадим сущность Person :

@Entity
@Table
public class Person implements Serializable {
@Id
@GeneratedValue
private Long id;
private String name;
private String password;
private String email;
private Long personNumber;
private Boolean isActive;
private String securityNumber;
private String departmentCode;
@JoinColumn(name = "addressId", referencedColumnName = "id")
private Address address;
//getters and setters
}

Поле адреса — это поле, указанное в объекте Address :

@Entity
@Table
public class Address implements Serializable {
@Id
@GeneratedValue
private Long id;
private String streetAddress;
//getters and setters
}

В этом руководстве мы будем использовать эту сущность Person для демонстрации наших примеров.

4. Ограничения столбцов

Когда у нас есть готовая модель, мы можем реализовать наше первое уникальное ограничение.

Давайте рассмотрим нашу сущность Person , которая содержит информацию о человеке. У нас есть первичный ключ для столбца id . Этот объект также содержит PersonNumber, который не содержит повторяющихся значений. Кроме того, мы не можем определить первичный ключ, потому что он уже есть в нашей таблице.

В этом случае мы можем использовать ограничения уникальности столбца, чтобы убедиться, что в поле PersonNumber не введены повторяющиеся значения . JPA позволяет нам добиться этого с помощью аннотации @Column с уникальным атрибутом.

В следующих разделах мы рассмотрим аннотацию @Column , а затем узнаем, как ее реализовать.

4.1. @Столбец (уникальный = истина)

Столбец типа аннотации используется для указания сопоставленного столбца для постоянного свойства или поля.

Давайте посмотрим на определение:

@Target(value={METHOD,FIELD})
@Retention(value=RUNTIME)
public @interface Column {
boolean unique;
//other elements
}

Уникальный атрибут указывает, является ли столбец уникальным ключом . Это ярлык для аннотации UniqueConstraint , который полезен, когда ограничение уникального ключа соответствует только одному столбцу.

Мы увидим, как определить его в следующем разделе.

4.2. Определение ограничений столбца

Всякий раз, когда ограничение уникальности основано только на одном поле, мы можем использовать @Column(unique=true) для этого столбца.

Давайте определим уникальное ограничение для поля personNumber :

@Column(unique=true)
private Long personNumber;

Когда мы выполняем процесс создания схемы, мы можем проверить его по журналам:

[main] DEBUG org.hibernate.SQL -
alter table Person add constraint UK_d44q5lfa9xx370jv2k7tsgsqt unique (personNumber)

Точно так же, если мы хотим ограничить человека для регистрации с уникальным адресом электронной почты, мы можем добавить уникальное ограничение в поле электронной почты :

@Column(unique=true)
private String email;

Давайте выполним процесс создания схемы и проверим ограничения:

[main] DEBUG org.hibernate.SQL -
alter table Person add constraint UK_585qcyc8qh7bg1fwgm1pj4fus unique (email)

Хотя это полезно, когда мы хотим установить уникальное ограничение для одного столбца, иногда нам может понадобиться добавить уникальные ограничения для составного ключа, который представляет собой комбинацию столбцов. Чтобы определить составной уникальный ключ, мы можем использовать табличные ограничения. Мы обсудим это в следующем разделе.

5. Ограничения таблицы

Составной уникальный ключ — это уникальный ключ, состоящий из комбинации столбцов. Чтобы определить составной уникальный ключ, мы можем добавить ограничения на таблицу вместо столбца. JPA помогает нам достичь этого с помощью аннотации @UniqueConstraint .

5.1. @UniqueConstraint Аннотация

Тип аннотации UniqueConstraint указывает, что уникальное ограничение должно быть включено в сгенерированный DDL (язык определения данных) для таблицы.

Давайте посмотрим на определение:

@Target(value={})
@Retention(value=RUNTIME)
public @interface UniqueConstraint {
String name() default "";
String[] columnNames();
}

Как мы видим, name и columnNames типа String и String [] соответственно являются элементами аннотации, которые могут быть указаны для аннотации UniqueConstraint .

Мы более подробно рассмотрим каждый из параметров в следующем разделе на примерах.

5.2. Определение уникальных ограничений

Давайте рассмотрим нашу сущность Person . У человека не должно быть повторяющихся записей для активного статуса. Другими словами, для ключа, состоящего из personNumber и isActive , не будет повторяющихся значений . Здесь нам нужно добавить уникальные ограничения, которые охватывают несколько столбцов.

JPA помогает нам достичь этого с помощью аннотации @UniqueConstraint . Мы используем его в аннотации @Table под атрибутом uniqueConstraints . Не забудем указать имена столбцов:

@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "personNumber", "isActive" }) })

Мы можем проверить это после создания схемы:

[main] DEBUG org.hibernate.SQL -
alter table Person add constraint UK5e0bv5arhh7jjhsls27bmqp4a unique (personNumber, isActive)

Здесь следует отметить, что если мы не указываем имя, это значение создается провайдером. Начиная с JPA 2.0, мы можем указать имя для нашего уникального ограничения:

@Table(uniqueConstraints = { @UniqueConstraint(name = "UniqueNumberAndStatus", columnNames = { "personNumber", "isActive" }) })

И мы можем подтвердить то же самое:

[main] DEBUG org.hibernate.SQL -
alter table Person add constraint UniqueNumberAndStatus unique (personNumber, isActive)

Здесь мы добавили уникальные ограничения на набор столбцов. Мы также можем добавить несколько уникальных ограничений, что означает уникальные ограничения для нескольких наборов столбцов. Мы сделаем это в следующем разделе.

5.3. Несколько уникальных ограничений для одного объекта

Таблица может иметь несколько уникальных ограничений. В последнем разделе мы определили уникальные ограничения для составного ключа: personNumber и статус isActive . В этом разделе мы добавим ограничения на комбинацию securityNumber и DepartmentCode .

Давайте соберем наши уникальные индексы и сразу их укажем. Мы делаем это, повторяя аннотацию @UniqueConstraint в фигурных скобках и разделяя их запятой:

@Table(uniqueConstraints = {
@UniqueConstraint(name = "UniqueNumberAndStatus", columnNames = {"personNumber", "isActive"}),
@UniqueConstraint(name = "UniqueSecurityAndDepartment", columnNames = {"securityNumber", "departmentCode"})})

Теперь посмотрим логи и проверим ограничения:

[main] DEBUG org.hibernate.SQL -
alter table Person add constraint UniqueNumberAndStatus unique (personNumber, isActive)
[main] DEBUG org.hibernate.SQL -
alter table Person add constraint UniqueSecurityAndDepartment unique (securityNumber, departmentCode)

До сих пор мы определяли уникальные ограничения для полей в одном и том же объекте. Однако в некоторых случаях у нас могут быть ссылки на поля из других сущностей, и нам необходимо обеспечить уникальность этих полей. Мы обсудим это в следующем разделе.

6. Уникальные ограничения столбца таблицы, на который ссылаются,

Когда мы создаем две или более таблиц, которые связаны друг с другом, они часто связаны столбцом в одной таблице, ссылающимся на первичный ключ другой таблицы. Этот столбец называется «внешним ключом». Например, объекты Person и Address связаны через поле addressId . Следовательно, addressId действует как столбец таблицы, на который ссылаются.

Мы можем определить уникальные ограничения для столбцов, на которые ссылаются . Сначала мы реализуем его для одного столбца, а затем для нескольких столбцов.

6.1. Ограничения для одного столбца

В нашей сущности Person у нас есть поле адреса , которое ссылается на сущность Address . У человека должен быть уникальный адрес.

Итак, давайте определим уникальное ограничение для поля адреса Person :

@Column(unique = true)
private Address address;

Теперь давайте быстро проверим это ограничение:

[main] DEBUG org.hibernate.SQL -
alter table Person add constraint UK_7xo3hsusabfaw1373oox9uqoe unique (address)

Мы также можем определить несколько ограничений столбца для столбца таблицы, на который указывает ссылка, как мы увидим в следующем разделе.

6.2. Ограничения нескольких столбцов

Мы можем указать уникальные ограничения на комбинацию столбцов. Как указывалось ранее, для этого мы можем использовать табличные ограничения.

Давайте определим уникальные ограничения для personNumber и адреса и добавим их в массив uniqueConstraints :

@Entity
@Table(uniqueConstraints =
{ //other constraints
@UniqueConstraint(name = "UniqueNumberAndAddress", columnNames = { "personNumber", "address" })})

Наконец, давайте посмотрим на уникальные ограничения:

[main] DEBUG org.hibernate.SQL -
alter table Person add constraint UniqueNumberAndAddress unique (personNumber, address)

7. Заключение

Ограничения уникальности не позволяют двум записям иметь одинаковые значения в столбце или наборе столбцов.

В этой статье мы узнали, как определить уникальные ограничения в JPA. Во-первых, мы сделали небольшой обзор уникальных ограничений. Затем мы обсудили аннотации @Column(unique=true) и @UniqueConstraint для определения уникальных ограничений для одного и нескольких столбцов соответственно.

Как всегда, примеры из этой статьи доступны на GitHub .