Définition d'index dans JPA

1. Introduction

Dans ce didacticiel, nous aborderons la définition des index à l'aide de l' annotation @Index de JPA . À travers des exemples, nous allons apprendre à définir notre premier index à l'aide de JPA et Hibernate. Après cela, nous allons modifier la définition en montrant des moyens supplémentaires de personnaliser l'index.

2. Annotation @Index

Commençons par faire un bref récapitulatif. L'index de base de données est une structure de données qui améliore la vitesse des opérations de récupération de données sur une table au prix d'écritures et d'espace de stockage supplémentaires. Il s'agit principalement d'une copie de colonnes de données sélectionnées à partir d'une seule table. Nous devons créer des index pour augmenter les performances sur notre couche de persistance.

JPA nous permet d'y parvenir en définissant des index à partir de notre code en utilisant @Index . Cette annotation est interprétée par le processus de génération de schéma, créant automatiquement des artefacts. Notez qu'il n'est pas nécessaire de spécifier un index pour nos entités.

Maintenant, jetons un œil à la définition.

2.1. javax.persistence.Index

Le support d'index a finalement été ajouté dans la spécification JPA 2.1 par javax.persistence.Index . Cette annotation nous permet de définir un index pour notre table et de le personnaliser en conséquence:

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

Comme nous pouvons le voir, seul l' attribut columnList est obligatoire, que nous devons définir. Nous examinerons plus en détail chacun des paramètres plus tard, en passant par des exemples.

2.2. JPA contre Hibernate

Nous savons que JPA n'est qu'une spécification. Pour fonctionner correctement, nous devons également spécifier un fournisseur de persistance. Par défaut, le Hibernate Framework est l'implémentation de JPA fournie par Spring. Pour en savoir plus, vous pouvez lire ici.

Nous devons nous rappeler que la prise en charge de l'index a été ajoutée très tardivement au JPA. Avant cela, de nombreux cadres ORM prennent en charge les index en introduisant leur propre implémentation personnalisée, qui peut fonctionner différemment. Le framework Hibernate l'a également fait et a introduit l' annotation org.hibernate.annotations.Index . Tout en travaillant avec ce framework, nous devons faire attention qu'il soit obsolète depuis le support de la spécification JPA 2.1, et nous devrions utiliser celui de JPA.

Maintenant, lorsque nous avons une certaine expérience technique, nous pouvons passer par des exemples et définir notre premier index dans JPA.

3. Définition de l ' @Index

Dans cette section, nous implémentons notre index. Plus tard, nous essaierons de le modifier, en présentant différentes possibilités de personnalisation.

Avant de commencer, nous devons initialiser correctement notre projet et définir un modèle.

Implémentons une entité Student :

@Entity @Table public class Student implements Serializable { @Id @GeneratedValue private Long id; private String firstName; private String lastName; // getters, setters }

Lorsque nous avons notre modèle, implémentons le premier index. Tout ce que nous avons à faire est d'ajouter une annotation @Index . Nous faisons cela dans l' annotation @Table sous l' attribut indexes . N'oublions pas de préciser le nom de la colonne:

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

Nous avons déclaré le tout premier index en utilisant la colonne firstName . Lorsque nous exécutons le processus de création de schéma, nous pouvons le valider:

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

Il est maintenant temps de modifier notre déclaration montrant des fonctionnalités supplémentaires.

3.1. @Index Name

Comme nous pouvons le voir, notre index doit avoir un nom. Par défaut, si nous ne le spécifions pas, c'est une valeur générée par le fournisseur. Lorsque nous voulons avoir une étiquette personnalisée, nous devons simplement ajouter l' attribut name :

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

Cette variante crée un index avec un nom défini par l'utilisateur:

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

De plus, nous pouvons créer notre index dans les différents schémas en spécifiant le nom du schéma dans le nom :

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

3.2. Multicolonne @Index

Maintenant, regardons de plus près la syntaxe columnList :

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

Comme nous le savons déjà, nous pouvons spécifier les noms de colonnes à inclure dans l'index. Bien sûr, nous pouvons spécifier plusieurs colonnes dans l'index unique. Nous faisons cela en séparant les noms par une virgule:

@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)

Notez que le fournisseur de persistance doit respecter l'ordre spécifié des colonnes. Dans notre exemple, les index sont légèrement différents, même s'ils spécifient le même ensemble de colonnes.

3.3. @Index Order

Comme nous avons examiné la syntaxe dans la section précédente, nous pouvons également spécifier des valeurs ASC (ascendant) et DESC (descendant) après le nom_colonne . Nous l'utilisons pour définir l'ordre de tri des valeurs dans la colonne indexée:

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

Nous pouvons spécifier l'ordre de chaque colonne. Sinon, l'ordre croissant est supposé.

3.4. @Index Unicité

The last optional parameter is a unique attribute, which defines whether the index is unique. A unique index ensures that the indexed fields don't store duplicate values. By default, it's false. If we want to change it, we can declare:

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

When we create an index in that way, we add a uniqueness constraint on our columns, similarly, how as a unique attribute on @Column annotation do. @Index has an advantage over @Column due to the possibility to declare multi-column unique constraint:

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

3.5. Multiple @Index on a Single Entity

So far, we've implemented different variants of the index. Of course, we're not limited to declaring a single index on the entity. Let's collect our declarations and specify every single index at once. We do that by repeating @Index annotation in braces and separated by a comma:

@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

What is more, we can also create multiple indexes for the same set of columns.

3.6. Primary Key

When we talk about indexes, we have to stop for a while at primary keys. As we know, every entity managed by the EntityManager must specify an identifier that is mapped into the primary key.

Generally, the primary key is a specific type of unique index. It's worth adding that we don't have to declare the definition of this key in the way presented before. Everything is done automatically by the @Id annotation.

3.7. Non-entity @Index

After we've learned different ways to implement indexes, we should mention that @Table isn't the only place to specify them. In the same way, we can declare indexes in @SecondaryTable, @CollectionTable, @JoinTable, @TableGenerator annotations. Those examples aren't covered in this article. For more details, please check the javax.persistence JavaDoc.

4. Conclusion

Dans cet article, nous avons discuté de la déclaration d'index à l'aide de JPA. Nous avons commencé par passer en revue les connaissances générales à leur sujet. Plus tard, nous avons implémenté notre premier index et, grâce à des exemples, avons appris à le personnaliser en changeant de nom, en incluant les colonnes, l'ordre et l'unicité. En fin de compte, nous avons parlé des clés primaires et des moyens et des endroits supplémentaires où nous pouvons les déclarer.

Comme toujours, les exemples de l'article sont disponibles à l'adresse over sur GitHub.