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

Определение индексов в JPA

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

1. Введение

В этом руководстве мы обсудим определение индексов с помощью аннотации JPA @Index . На примерах мы узнаем, как определить наш первый индекс с помощью JPA и Hibernate. После этого мы собираемся изменить определение, показав дополнительные способы настройки индекса.

2. @Индексная аннотация

Давайте начнем с краткого обзора. Индекс базы данных — это структура данных, которая повышает скорость операций извлечения данных из таблицы за счет дополнительных операций записи и места для хранения. В основном это копия выбранных столбцов данных из одной таблицы. Мы должны создать индексы, чтобы повысить производительность на нашем уровне сохраняемости.

JPA позволяет нам добиться этого, определяя индексы из нашего кода с помощью @Index . Эта аннотация интерпретируется процессом генерации схемы, автоматически создавая артефакты. Обратите внимание, что нет необходимости указывать какой-либо индекс для наших сущностей.

Теперь давайте посмотрим на определение.

2.1. javax.persistence.Index

Наконец, поддержка индексов была добавлена в спецификацию JPA 2.1 с помощью javax.persistence.Index . Эта аннотация позволяет нам определить индекс для нашей таблицы и соответствующим образом настроить его:

@Target({})
@Retention(RUNTIME)
public @interface Index {
String name() default "";
String columnList();
boolean unique() default false;
}

Как мы видим, обязательным является только атрибут columnList , который мы должны определить. Позже мы подробнее рассмотрим каждый из параметров на примерах.

Здесь следует отметить один аспект: аннотация не поддерживает изменение алгоритма индексации по умолчанию — btree.

2.2. JPA против Hibernate

Мы знаем, что JPA — это только спецификация. Для корректной работы нам также необходимо указать поставщика постоянства. По умолчанию Hibernate Framework является реализацией JPA, поставляемой Spring. Подробнее об этом вы можете прочитать здесь .

Мы должны помнить, что поддержка индексов была добавлена в JPA очень поздно. До этого многие платформы ORM поддерживали индексы, вводя собственную реализацию, которая могла работать по-разному. Hibernate Framework также сделал это и представил аннотацию org.hibernate.annotations.Index . Работая с этой структурой, мы должны быть осторожны, поскольку она устарела с момента поддержки спецификации JPA 2.1, и мы должны использовать ее.

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

3. Определение @Index

В этом разделе мы реализуем наш index. Позже мы попробуем изменить его, представив различные возможности настройки.

Прежде чем мы начнем, нам нужно правильно инициализировать наш проект и определить модель .

Давайте реализуем сущность Student :

@Entity
@Table
public class Student implements Serializable {
@Id
@GeneratedValue
private Long id;
private String firstName;
private String lastName;

// getters, setters
}

Когда у нас есть наша модель, давайте реализуем первый индекс. Все, что нам нужно сделать, это добавить аннотацию @Index . Мы делаем это в аннотации @Table под атрибутом indexes . Не забудем указать имя столбца:

@Table(indexes = @Index(columnList = "firstName"))

Мы объявили самый первый индекс, используя столбец firstName . Когда мы выполняем процесс создания схемы, мы можем проверить его:

[main] DEBUG org.hibernate.SQL -
create index IDX2gdkcjo83j0c2svhvceabnnoh on Student (firstName)

Теперь пришло время изменить наше объявление, показав дополнительные функции.

3.1. @ Имя индекса

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

@Index(name = "fn_index", columnList = "firstName")

Этот вариант создает индекс с определяемым пользователем именем:

[main] DEBUG org.hibernate.SQL -
create index fn_index on Student (firstName)

Более того, мы можем создать наш индекс в другой схеме, указав имя схемы в имени :

@Index(name = "schema2.fn_index", columnList = "firstName")

3.2. Многоколоночный @Index ``

Теперь давайте подробнее рассмотрим синтаксис столбцаList :

column ::= index_column [,index_column]*
index_column ::= column_name [ASC | DESC]

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

@Index(name = "mulitIndex1", columnList = "firstName, lastName")

@Index(name = "mulitIndex2", columnList = "lastName, firstName")
[main] DEBUG org.hibernate.SQL -
create index mulitIndex1 on Student (firstName, lastName)

[main] DEBUG org.hibernate.SQL -
create index mulitIndex2 on Student (lastName, firstName)

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

3.3. @ Порядок индекса

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

@Index(name = "mulitSortIndex", columnList = "firstName, lastName DESC")
[main] DEBUG org.hibernate.SQL -
create index mulitSortIndex on Student (firstName, lastName desc)

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

3.4. @Индекс Уникальность

Последний необязательный параметр — это уникальный атрибут, который определяет, является ли индекс уникальным. Уникальный индекс гарантирует, что в проиндексированных полях не будут храниться повторяющиеся значения. По умолчанию это ложь . Если мы хотим изменить его, мы можем объявить:

@Index(name = "uniqueIndex", columnList = "firstName", unique = true)
[main] DEBUG org.hibernate.SQL -
alter table Student add constraint uniqueIndex unique (firstName)

Когда мы создаем индекс таким образом, мы добавляем ограничение уникальности для наших столбцов, аналогично тому, как это делается в качестве уникального атрибута в аннотации @Column . @Index имеет преимущество перед @Column из-за возможности объявить уникальное ограничение для нескольких столбцов:

@Index(name = "uniqueMulitIndex", columnList = "firstName, lastName", unique = true)

3.5. Несколько @Index для одного объекта

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

@Entity
@Table(indexes = {
@Index(columnList = "firstName"),
@Index(name = "fn_index", columnList = "firstName"),
@Index(name = "mulitIndex1", columnList = "firstName, lastName"),
@Index(name = "mulitIndex2", columnList = "lastName, firstName"),
@Index(name = "mulitSortIndex", columnList = "firstName, lastName DESC"),
@Index(name = "uniqueIndex", columnList = "firstName", unique = true),
@Index(name = "uniqueMulitIndex", columnList = "firstName, lastName", unique = true)
})
public class Student implements Serializable

Более того, мы также можем создать несколько индексов для одного и того же набора столбцов.

3.6. Первичный ключ

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

Как правило, первичный ключ представляет собой особый тип уникального индекса. Стоит добавить, что нам не нужно объявлять определение этого ключа так, как это было представлено ранее. Все делается автоматически по аннотации @Id .

3.7. @Index , не являющийся сущностью ``

После того, как мы узнали о различных способах реализации индексов, мы должны упомянуть, что @Table — не единственное место, где их можно указать. Точно так же мы можем объявить индексы в аннотациях @SecondaryTable , @CollectionTable, @JoinTable , @TableGenerator . Эти примеры не рассматриваются в этой статье. Для получения более подробной информации см . JavaDoc javax.persistence .

4. Вывод

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

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