105 votes

Spécifier un index (clé non unique) avec JPA

Comment définir un champ, par exemple email comme ayant un index utilisant les annotations JPA. Nous avons besoin d'une clé non-unique sur email parce qu'il y a littéralement des millions de requêtes sur ce champ par jour, et c'est un peu lent sans la clé.

@Entity
@Table(name="person", 
       uniqueConstraints=@UniqueConstraint(columnNames={"code", "uid"}))
public class Person {
    // Unique on code and uid
    public String code;
    public String uid;

    public String username;
    public String name;
    public String email;
}

J'ai vu une annotation spécifique à Hibernate, mais j'essaie d'éviter les solutions spécifiques aux fournisseurs, car nous sommes encore en train de choisir entre Hibernate et Datanucleus.

6 votes

Ce serait formidable si vous pouviez mettre à jour la réponse pour que les gens sachent qu'il existe un moyen de le faire avec JPA 2.1.

2 votes

Pourquoi n'acceptez-vous pas la réponse la plus votée ?

222voto

borjab Points 1839

Avec JPA 2.1, vous devriez être en mesure de le faire.

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Table;

@Entity
@Table(name = "region",
       indexes = {@Index(name = "my_index_name",  columnList="iso_code", unique = true),
                  @Index(name = "my_index_name2", columnList="name",     unique = false)})
public class Region{

    @Column(name = "iso_code", nullable = false)
    private String isoCode;

    @Column(name = "name", nullable = false)
    private String name;

}

0 votes

Merci à Alvin pour sa réponse. (+1 vote). Mais j'ai dû chercher quelques éléments et j'espère que cet exemple vous facilitera la vie.

2 votes

Exactement ce que je cherchais - un extrait de code simple et propre - pas seulement une description de l'ensemble. Merci +1.

2 votes

@borjab - Pouvez-vous me donner un indice où je peux trouver un exemple ou une spécification "officielle" pour l'utilisation de l'option @Index à l'intérieur de l'annotation @Table annotation ? J'ai cherché sur JSR 338 mais je ne l'ai pas trouvé là. Votre post est très utile pour moi.

31voto

Alvin Thompson Points 1734

JPA 2.1 ajoute (enfin) le support des index et des clés étrangères ! Voir ce blog pour les détails. JPA 2.1 fait partie de Java EE 7, qui est sorti .

Si vous aimez vivre sur le fil du rasoir, vous pouvez obtenir les derniers instantanés d'eclipselink sur leur site web. référentiel maven (groupId:org.eclipse.persistence, artifactId:eclipselink, version:2.5.0-SNAPSHOT). Pour les annotations JPA uniquement (qui devraient fonctionner avec n'importe quel fournisseur dès qu'il supportera la version 2.1), utilisez artifactID:javax.persistence, version:2.1.0-SNAPSHOT.

Je l'utilise pour un projet qui ne sera terminé qu'après sa sortie, et je n'ai pas remarqué de problème grave (bien que je ne fasse rien de trop complexe avec).

MISE À JOUR (26 Sep 2013) : Aujourd'hui les versions release et release candidate d'eclipselink sont disponibles dans le dépôt central (principal), vous n'avez donc plus besoin d'ajouter le dépôt eclipselink dans les projets Maven. La dernière version release est la 2.5.0 mais la 2.5.1-RC3 est également présente. Je passerais à la 2.5.1 dès que possible en raison de problèmes avec la version 2.5.0 (le truc modelgen ne fonctionne pas).

10voto

James Points 1

Dans JPA 2.1, vous devez effectuer les opérations suivantes

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.Table;

@Entity(name="TEST_PERSON")
@Table(
    name="TEST_PERSON", 
    indexes = {
       @Index(name = "PERSON_INDX_0", columnList = "age"),
       @Index(name = "PERSON_INDX_1", columnList = "fName"),
       @Index(name = "PERSON_INDX_1", columnList = "sName")  })
public class TestPerson {

    @Column(name = "age", nullable = false)
    private int age;

    @Column(name = "fName", nullable = false)
    private String firstName;

    @Column(name = "sName", nullable = false)
    private String secondName;

    @Id
    private long id;

    public TestPerson() {
    }
}

Dans l'exemple ci-dessus, la table TEST_PERSON aura 3 index :

  • index unique sur la clé primaire ID

  • indice sur l'AGE

  • indice composé sur FNAME, SNAME

Note 1 : Vous obtenez l'index composé en ayant deux annotations @Index avec le même nom.

Note 2 : Vous spécifiez le nom de la colonne dans columnList et non pas fieldName.

0 votes

Mais l'avantage de l'index composé ? il utilise la recherche binaire lors de la recherche ou impose une contrainte unique.

5voto

Pascal Thivent Points 295221

J'aimerais vraiment pouvoir spécifier les index de base de données de manière standardisée mais, malheureusement, cela ne fait pas partie de la spécification JPA (peut-être parce que la prise en charge de la génération de DDL n'est pas requise par la spécification JPA, ce qui constitue une sorte de blocage pour une telle fonctionnalité).

Vous devrez donc compter sur une extension spécifique au fournisseur pour cela. Hibernate, OpenJPA et EclipseLink offrent clairement une telle extension. Je ne peux pas confirmer pour DataNucleus mais puisque la définition des index fait partie de JDO, je suppose que c'est le cas.

J'espère vraiment que la prise en charge de l'index sera normalisée dans les prochaines versions de la spécification et, par conséquent, je ne suis pas d'accord avec les autres réponses, je ne vois pas de bonne raison de ne pas inclure une telle chose dans JPA (en particulier parce que la base de données n'est pas toujours sous votre contrôle) pour une prise en charge optimale de la génération de DDL.

Au fait, je vous suggère de télécharger la spécification JPA 2.0.

4voto

Tassos Bassoukos Points 6872

Pour autant que je sache, il n'existe pas de moyen de spécifier les index entre les fournisseurs JPA. Cependant, vous pouvez toujours les créer à la main directement dans la base de données, la plupart des bases de données les récupèrent automatiquement lors de la planification des requêtes.

2 votes

Lol, c'est en supposant que vous avez des DBA qui font le travail d'un DBA ( :

3 votes

Je trouve un peu étrange qu'il y ait une façon de faire "unique" mais pas une façon de faire un index.

7 votes

@Jacob - Et bien il est important de savoir au niveau de l'application si un champ sera unique ou non. Les index, d'un autre côté, ont pour but d'optimiser l'accès à la base de données. Il n'est pas nécessaire (pour autant que je le sache) de savoir si une colonne est un index ou non au niveau de la couche Java. Comme vous l'avez dit, le DBA peut mettre en place un index s'il semble qu'une colonne particulière en bénéficierait.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X